c057e2872b7758cd8decf9d50aeccf9fdc883f12
[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 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);
167 }
168 else
169 stateCell.innerHTML = "&nbsp;&nbsp;";
170
171 linkCell.appendChild(img);
172 linkCell.appendChild(a);
173 newRow.appendChild(indentCell);
174 newRow.appendChild(stateCell);
175 newRow.appendChild(linkCell);
176
177
178 this.root.insertBefore(newRow, parentRow.nextSibling);
179 } //end for
180
181 if (incTableDepth) {
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];
187
188 if (lastCell.nullColSpan) {
189 lastCell.nullColSpan = false;
190 lastColspan = 0;
191 }
192 else
193 lastColspan = parseInt(lastCell.getAttribute("colspan"));
194
195 lastCell.colSpan = lastColspan + 1;
196 }
197 }
198 };
199
200 /*
201 * collapse the tree: removes deeper rows after the 'baseRow' passed.
202 */
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;
210
211 while (nextRow) {
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);
218 nextRow = nextRow2;
219 continue;
220 }
221 break;
222 }
223 nextRow = nextRow.nextSibling; // text node
224 }
225
226 // recalc colspans for Safari
227 var maxDepth = depthCpt.length - 1;
228 var depthReduction = 0;
229 while (depthCpt[maxDepth - depthReduction] == 0) {
230 depthCpt.pop();
231 depthReduction++;
232 }
233
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;
241 }
242 }
243 };
244 })();