--- /dev/null
+// (c) BenoƮt PIN 2006
+// http://plinn.org
+// Licence GPL
+
+var TreeMaker;
+
+(function() {
+/* root -> base node (typically a tbody or a table)
+* filter -> comma separated list of portal_types
+*/
+TreeMaker = function (root, filter, baseImgUrl) {
+ this.root = root;
+ var tm = this;
+ this.root.onclick = function(evt) { tm.refreshTree(evt); };
+ this.filter = filter;
+ this.baseImgUrl = baseImgUrl;
+ this.depthCpt = new Array();
+ this._lastAniImg = null;
+
+ // preload images
+ var images = ['pl.png', 'pl_ani.png', 'mi.png', 'mi_ani.png'], img;
+ for (var i=0 ; i < images.length ; i++) {
+ img = new Image();
+ img.src = this.baseImgUrl + images[i];
+ }
+}
+
+/*
+* expand / collapse handler
+* object loading trigger
+*/
+TreeMaker.prototype.refreshTree = function (evt) {
+ var target = getTargetedObject(evt);
+ if (target.blur)
+ target.blur();
+
+ if (target.tagName == 'IMG') {
+ target.parentNode.blur();
+ var srcParts = target.src.split("/");
+ var imgId = srcParts[srcParts.length-1];
+ var parentTd = target.parentNode.parentNode;
+ var parentRow = parentTd.parentNode;
+
+
+ switch (imgId) {
+ case "pl.png" :
+ case "pl_ani.png" :
+ var linkCell = parentTd.nextSibling;
+ while (linkCell.nodeType != 1)
+ linkCell = linkCell.nextSibling;
+
+ var obUrl = linkCell.getElementsByTagName("A")[0].href;
+
+ var req = new XMLHttpRequest();
+ var tm = this;
+ req.onreadystatechange = function() {
+ switch (req.readyState) {
+ case 1:
+ showProgressImage();
+ break;
+ case 4:
+ hideProgressImage();
+ tm.importRows(req, parentRow);
+ };
+ };
+ target.src = this.baseImgUrl + "mi_ani.png";
+ this._lastAniImg = target;
+ window.setTimeout(function(){tm._removeLastAniImg();}, 500);
+
+ req.open("POST", obUrl + "/xml_nav_tree", true);
+ req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
+ req.send("filter=" + encodeURIComponent(this.filter) +
+ "&root_name=" + encodeURIComponent(this.root.id) +
+ "&expansion=" + encodeURIComponent(this.getExpansion()));
+
+ break;
+
+ case "mi.png" :
+ case "mi_ani.png" :
+ this.removeChildNodes(parentRow);
+ target.src = this.baseImgUrl + "pl_ani.png";
+ this._lastAniImg = target;
+ var tm = this;
+ window.setTimeout(function(){tm._removeLastAniImg();}, 500);
+ document.cookie = encodeURIComponent(this.root.id) + '-state=' + encodeURIComponent(this.getExpansion()) +
+ ';path=/';
+ break;
+ } // end switch (imgId)
+ disableDefault(evt);
+ disablePropagation(evt);
+ }
+};
+
+
+TreeMaker.prototype._removeLastAniImg = function() {
+ if (this._lastAniImg) {
+ this._lastAniImg.src = this._lastAniImg.src.replace("_ani", "");
+ }
+};
+
+TreeMaker.prototype.getExpansion = function() {
+ var rows = this.root.getElementsByTagName('TR');
+ var row, cells, stateCell, button, expid, node_depth, last_depth = -1, dd, step;
+ var steps = new Array();
+ steps.push(this.root.getAttribute('name'));
+
+ var expanded = (/.*mi\.png$|.*mi_ani\.png$/);
+ for(i=0 ; i < rows.length ; i++) {
+ row = rows[i];
+ cells = row.getElementsByTagName('TD');
+ stateCell = cells[cells.length-2]; // cell where the +/- button is
+ button = stateCell.getElementsByTagName('IMG');
+ if (! button.length)
+ continue;
+ button = button[0];
+ if (expanded.test(button.src)) {
+ expid = button.parentNode.getAttribute("name");
+ node_depth = cells[0].getAttribute('colspan') || 0;
+ dd = last_depth - node_depth + 1;
+ last_depth = node_depth;
+ if (dd > 0) {
+ step = '';
+ for (var j = 0 ; j < dd ; j++)
+ step = step + '_';
+ steps.push(step);
+ }
+ steps.push(expid);
+ }
+ }
+ return steps.join(':');
+};
+
+
+/*
+* expand the tree: sends request and imports rows based on xml response.
+*/
+TreeMaker.prototype.importRows = function(req, parentRow) {
+ var rows = req.responseXML.documentElement.getElementsByTagName("row");
+ var clickedCells = parentRow.getElementsByTagName("TD");
+ var row, newRow, indentCell, stateCell, linkCell, img, a, indentValue, colspan,
+ incTableDepth=false, cols, linkCellColSpan;
+
+ for (var i = 0 ; i < rows.length ; i++ ) {
+ row = rows[i];
+
+
+ newRow = document.createElement("TR");
+ indentCell = document.createElement("TD");
+ stateCell = document.createElement("TD");
+ stateCell.width = "16";
+ linkCell = document.createElement("TD");
+ linkCell.width = "99%";
+
+
+ if (clickedCells.length == 3) {
+ indentValue = parseInt(clickedCells[0].getAttribute("colspan"));
+ colspan = parseInt(clickedCells[2].getAttribute("colspan"));
+ }
+ else {
+ indentValue = 0;
+ colspan = parseInt(clickedCells[1].getAttribute("colspan"));
+ }
+
+ cols = indentValue + colspan;
+
+ if (colspan == 1)
+ incTableDepth = true;
+
+ indentCell.colSpan = indentValue + 1;
+ if (!this.depthCpt[indentValue])
+ this.depthCpt[indentValue] = 1;
+ else
+ this.depthCpt[indentValue] += 1;
+
+ // IE : it's not possible to set colSpan attr to 0 :-(((
+ linkCellColSpan = cols - indentValue - 1
+ if (linkCellColSpan == 0)
+ linkCell.nullColSpan = true;
+ else
+ linkCell.colSpan = linkCellColSpan;
+
+ img = document.createElement("IMG");
+ img.src = row.getAttribute("icon");
+ img.height = row.getAttribute("height");
+ img.width = row.getAttribute("width");
+ a = document.createElement("A");
+
+ a.setAttribute("href", row.getAttribute("url"));
+ a.setAttribute("title", row.getAttribute("description"));
+ a.innerHTML = row.childNodes[0].nodeValue;
+
+ if (row.getAttribute("state") == "-1") {
+ var stateLink = document.createElement("A");
+ stateLink.href = ".";
+ stateLink.setAttribute("name", row.getAttribute("name"));
+ var stateImg = document.createElement("IMG");
+ stateImg.src = this.baseImgUrl + "pl.png";
+ stateImg.border = "0";
+ stateImg.height = "16";
+ stateImg.width = "16";
+ stateLink.appendChild(stateImg)
+ stateCell.appendChild(stateLink);
+ }
+ else
+ stateCell.innerHTML = " ";
+
+ linkCell.appendChild(img);
+ linkCell.appendChild(a);
+ newRow.appendChild(indentCell);
+ newRow.appendChild(stateCell);
+ newRow.appendChild(linkCell);
+
+
+ this.root.insertBefore(newRow, parentRow.nextSibling);
+ } //end for
+
+ if (incTableDepth) {
+ var rows = this.root.getElementsByTagName("TR");
+ var cells, lastCell, lastColspan;
+ for (var i = 0 ; i < rows.length ; i++) {
+ cells = rows[i].getElementsByTagName("TD");
+ lastCell = cells[cells.length - 1];
+
+ if (lastCell.nullColSpan) {
+ lastCell.nullColSpan = false;
+ lastColspan = 0;
+ }
+ else
+ lastColspan = parseInt(lastCell.getAttribute("colspan"));
+
+ lastCell.colSpan = lastColspan + 1;
+ }
+ }
+};
+
+/*
+* collapse the tree: removes deeper rows after the 'baseRow' passed.
+*/
+TreeMaker.prototype.removeChildNodes = function(baseRow) {
+ var baseCells = baseRow.getElementsByTagName("TD");
+ var baseColSpan = baseCells[baseCells.length-1].colSpan;
+ var nextRow = baseRow.nextSibling;
+ var tbody = baseRow.parentNode;
+ var depthCpt = this.depthCpt;
+ var nextCells, nextRow2;
+
+ while (nextRow) {
+ if (nextRow.nodeType == 1) {
+ nextCells = nextRow.getElementsByTagName("TD");
+ if (nextCells.length == 3 && nextCells[2].colSpan < baseColSpan) {
+ nextRow2 = nextRow.nextSibling;
+ depthCpt[nextCells[0].colSpan-1] -= 1;
+ tbody.removeChild(nextRow);
+ nextRow = nextRow2;
+ continue;
+ }
+ break;
+ }
+ nextRow = nextRow.nextSibling; // text node
+ }
+
+ // recalc colspans for Safari
+ var maxDepth = depthCpt.length - 1;
+ var depthReduction = 0;
+ while (depthCpt[maxDepth - depthReduction] == 0) {
+ depthCpt.pop();
+ depthReduction++;
+ }
+
+ if (depthReduction) {
+ var rows = tbody.getElementsByTagName("TR");
+ var cells, lastCell, lastColspan;
+ for (var i = 0 ; i < rows.length ; i++) {
+ cells = rows[i].getElementsByTagName("TD");
+ lastCell = cells[cells.length - 1];
+ lastCell.colSpan = parseInt(lastCell.colSpan) - depthReduction;
+ }
+ }
+};
+})();
\ No newline at end of file