228d405eef868bba51959af1cd18cb07351c1239
[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 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);
69
70 target.src = this.baseImgUrl + "mi_ani.gif";
71 this._lastAniImg = target;
72
73
74 window.setTimeout(function(){tm._removeLastAniImg();}, 500);
75 break;
76
77 case "mi.gif" :
78 case "mi_ani.gif" :
79 this.removeChildNodes(parentRow);
80 target.src = this.baseImgUrl + "pl_ani.gif";
81 this._lastAniImg = target;
82 var tm = this;
83 window.setTimeout(function(){tm._removeLastAniImg();}, 500);
84 break;
85 } // end switch (imgId)
86 disableDefault(evt);
87 disablePropagation(evt);
88 }
89 };
90
91
92 TreeMaker.prototype._removeLastAniImg = function() {
93 if (this._lastAniImg) {
94 this._lastAniImg.src = this._lastAniImg.src.replace("_ani", "");
95 }
96 };
97
98
99 /*
100 * expand the tree: sends request and imports rows based on xml response.
101 */
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;
107
108 for (var i = 0 ; i < rows.length ; i++ ) {
109 row = rows[i];
110
111
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%";
118
119
120 if (clickedCells.length == 3) {
121 indentValue = parseInt(clickedCells[0].getAttribute("colspan"));
122 colspan = parseInt(clickedCells[2].getAttribute("colspan"));
123 }
124 else {
125 indentValue = 0;
126 colspan = parseInt(clickedCells[1].getAttribute("colspan"));
127 }
128
129 cols = indentValue + colspan;
130
131 if (colspan == 1)
132 incTableDepth = true;
133
134 indentCell.colSpan = indentValue + 1;
135 if (!this.depthCpt[indentValue])
136 this.depthCpt[indentValue] = 1;
137 else
138 this.depthCpt[indentValue] += 1;
139
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;
144 else
145 linkCell.colSpan = linkCellColSpan;
146
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");
152
153 a.setAttribute("href", row.getAttribute("url"));
154 a.setAttribute("title", row.getAttribute("description"));
155 a.innerHTML = row.childNodes[0].nodeValue;
156
157 if (row.getAttribute("state") == "-1") {
158 var stateLink = document.createElement("A");
159 stateLink.href = ".";
160 stateLink.setAttribute("name", row.getAttribute("name"));
161 var stateImg = document.createElement("IMG");
162 stateImg.src = this.baseImgUrl + "pl.gif";
163 stateImg.border = "0";
164 stateImg.height = "16";
165 stateImg.width = "16";
166 stateLink.appendChild(stateImg)
167 stateCell.appendChild(stateLink);
168 }
169 else
170 stateCell.innerHTML = "&nbsp;&nbsp;";
171
172 linkCell.appendChild(img);
173 linkCell.appendChild(a);
174 newRow.appendChild(indentCell);
175 newRow.appendChild(stateCell);
176 newRow.appendChild(linkCell);
177
178
179 this.root.insertBefore(newRow, parentRow.nextSibling);
180 } //end for
181
182 if (incTableDepth) {
183 var rows = this.root.getElementsByTagName("TR");
184 var cells, lastCell, lastColspan;
185 for (var i = 0 ; i < rows.length ; i++) {
186 cells = rows[i].getElementsByTagName("TD");
187 lastCell = cells[cells.length - 1];
188
189 if (lastCell.nullColSpan) {
190 lastCell.nullColSpan = false;
191 lastColspan = 0;
192 }
193 else
194 lastColspan = parseInt(lastCell.getAttribute("colspan"));
195
196 lastCell.colSpan = lastColspan + 1;
197 }
198 }
199 };
200
201 /*
202 * collapse the tree: removes deeper rows after the 'baseRow' passed.
203 */
204 TreeMaker.prototype.removeChildNodes = function(baseRow) {
205 var baseCells = baseRow.getElementsByTagName("TD");
206 var baseColSpan = baseCells[baseCells.length-1].colSpan;
207 var nextRow = baseRow.nextSibling;
208 var tbody = baseRow.parentNode;
209 var depthCpt = this.depthCpt;
210 var nextCells, nextRow2;
211
212 while (nextRow) {
213 if (nextRow.nodeType == 1) {
214 nextCells = nextRow.getElementsByTagName("TD");
215 if (nextCells.length == 3 && nextCells[2].colSpan < baseColSpan) {
216 nextRow2 = nextRow.nextSibling;
217 depthCpt[nextCells[0].colSpan-1] -= 1;
218 tbody.removeChild(nextRow);
219 nextRow = nextRow2;
220 continue;
221 }
222 break;
223 }
224 nextRow = nextRow.nextSibling; // text node
225 }
226
227 // recalc colspans for Safari
228 var maxDepth = depthCpt.length - 1;
229 var depthReduction = 0;
230 while (depthCpt[maxDepth - depthReduction] == 0) {
231 depthCpt.pop();
232 depthReduction++;
233 }
234
235 if (depthReduction) {
236 var rows = tbody.getElementsByTagName("TR");
237 var cells, lastCell, lastColspan;
238 for (var i = 0 ; i < rows.length ; i++) {
239 cells = rows[i].getElementsByTagName("TD");
240 lastCell = cells[cells.length - 1];
241 lastCell.colSpan = parseInt(lastCell.colSpan) - depthReduction;
242 }
243 }
244 };
245 })();