aboutsummaryrefslogtreecommitdiff
path: root/www/analyzer/scripts/expandcollapse.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/analyzer/scripts/expandcollapse.js')
-rw-r--r--www/analyzer/scripts/expandcollapse.js191
1 files changed, 191 insertions, 0 deletions
diff --git a/www/analyzer/scripts/expandcollapse.js b/www/analyzer/scripts/expandcollapse.js
new file mode 100644
index 000000000000..593a9831c8b0
--- /dev/null
+++ b/www/analyzer/scripts/expandcollapse.js
@@ -0,0 +1,191 @@
+// expand/collapse button (expander) is added if height of a cell content
+// exceeds CLIP_HEIGHT px.
+var CLIP_HEIGHT = 135;
+
+// Height in pixels of an expander image.
+var EXPANDER_HEIGHT = 13;
+
+// Path to images for an expander.
+var imgPath = "./images/expandcollapse/";
+
+// array[group][cell] of { 'height', 'expanded' }.
+// group: a number; cells of the same group belong to the same table row.
+// cell: a number; unique index of a cell in a group.
+// height: a number, px; original height of a cell in a table.
+// expanded: boolean; is a cell expanded or collapsed?
+var CellsInfo = [];
+
+// Extracts group and cell indices from an id of the form identifier_group_cell.
+function getCellIdx(id) {
+ var idx = id.substr(id.indexOf("_") + 1).split("_");
+ return { 'group': idx[0], 'cell': idx[1] };
+}
+
+// Returns { 'height', 'expanded' } info for a cell with a given id.
+function getCellInfo(id) {
+ var idx = getCellIdx(id);
+ return CellsInfo[idx.group][idx.cell];
+}
+
+// Initialization, add nodes, collect info.
+function initExpandCollapse() {
+ if (!document.getElementById)
+ return;
+
+ var groupCount = 0;
+
+ // Examine all table rows in the document.
+ var rows = document.body.getElementsByTagName("tr");
+ for (var i=0; i<rows.length; i+=1) {
+
+ var cellCount=0, newGroupCreated = false;
+
+ // Examine all divs in a table row.
+ var divs = rows[i].getElementsByTagName("div");
+ for (var j=0; j<divs.length; j+=1) {
+
+ var expandableDiv = divs[j];
+
+ if (expandableDiv.className.indexOf("expandable") == -1)
+ continue;
+
+ if (expandableDiv.offsetHeight <= CLIP_HEIGHT)
+ continue;
+
+ // We found a div wrapping a cell content whose height exceeds
+ // CLIP_HEIGHT.
+ var originalHeight = expandableDiv.offsetHeight;
+ // Unique postfix for ids for generated nodes for a given cell.
+ var idxStr = "_" + groupCount + "_" + cellCount;
+ // Create an expander and an additional wrapper for a cell content.
+ //
+ // --- expandableDiv ----
+ // --- expandableDiv --- | ------ data ------ |
+ // | cell content | -> | | cell content | |
+ // --------------------- | ------------------ |
+ // | ---- expander ---- |
+ // ----------------------
+ var data = document.createElement("div");
+ data.className = "data";
+ data.id = "data" + idxStr;
+ data.innerHTML = expandableDiv.innerHTML;
+ with (data.style) { height = (CLIP_HEIGHT - EXPANDER_HEIGHT) + "px";
+ overflow = "hidden" }
+
+ var expander = document.createElement("img");
+ with (expander.style) { display = "block"; paddingTop = "5px"; }
+ expander.src = imgPath + "ellipses_light.gif";
+ expander.id = "expander" + idxStr;
+
+ // Add mouse calbacks to expander.
+ expander.onclick = function() {
+ expandCollapse(this.id);
+ // Hack for Opera - onmouseout callback is not invoked when page
+ // content changes dinamically and mouse pointer goes out of an element.
+ this.src = imgPath +
+ (getCellInfo(this.id).expanded ? "arrows_light.gif"
+ : "ellipses_light.gif");
+ }
+ expander.onmouseover = function() {
+ this.src = imgPath +
+ (getCellInfo(this.id).expanded ? "arrows_dark.gif"
+ : "ellipses_dark.gif");
+ }
+ expander.onmouseout = function() {
+ this.src = imgPath +
+ (getCellInfo(this.id).expanded ? "arrows_light.gif"
+ : "ellipses_light.gif");
+ }
+
+ expandableDiv.innerHTML = "";
+ expandableDiv.appendChild(data);
+ expandableDiv.appendChild(expander);
+ expandableDiv.style.height = CLIP_HEIGHT + "px";
+ expandableDiv.id = "cell"+ idxStr;
+
+ // Keep original cell height and its ecpanded/cpllapsed state.
+ if (!newGroupCreated) {
+ CellsInfo[groupCount] = [];
+ newGroupCreated = true;
+ }
+ CellsInfo[groupCount][cellCount] = { 'height' : originalHeight,
+ 'expanded' : false };
+ cellCount += 1;
+ }
+ groupCount += newGroupCreated ? 1 : 0;
+ }
+}
+
+function isElemTopVisible(elem) {
+ var body = document.body,
+ html = document.documentElement,
+ // Calculate expandableDiv absolute Y coordinate from the top of body.
+ bodyRect = body.getBoundingClientRect(),
+ elemRect = elem.getBoundingClientRect(),
+ elemOffset = Math.floor(elemRect.top - bodyRect.top),
+ // Calculate the absoute Y coordinate of visible area.
+ scrollTop = html.scrollTop || body && body.scrollTop || 0;
+ scrollTop -= html.clientTop; // IE<8
+
+
+ if (elemOffset < scrollTop)
+ return false;
+
+ return true;
+}
+
+// Invoked when an expander is pressed; expand/collapse a cell.
+function expandCollapse(id) {
+ var cellInfo = getCellInfo(id);
+ var idx = getCellIdx(id);
+
+ // New height of a row.
+ var newHeight;
+ // Smart page scrolling may be done after collapse.
+ var mayNeedScroll;
+
+ if (cellInfo.expanded) {
+ // Cell is expanded - collapse the row height to CLIP_HEIGHT.
+ newHeight = CLIP_HEIGHT;
+ mayNeedScroll = true;
+ }
+ else {
+ // Cell is collapsed - expand the row height to the cells original height.
+ newHeight = cellInfo.height;
+ mayNeedScroll = false;
+ }
+
+ // Update all cells (height and expanded/collapsed state) in a row according
+ // to the new height of the row.
+ for (var i = 0; i < CellsInfo[idx.group].length; i++) {
+ var idxStr = "_" + idx.group + "_" + i;
+ var expandableDiv = document.getElementById("cell" + idxStr);
+ expandableDiv.style.height = newHeight + "px";
+ var data = document.getElementById("data" + idxStr);
+ var expander = document.getElementById("expander" + idxStr);
+ var state = CellsInfo[idx.group][i];
+
+ if (state.height > newHeight) {
+ // Cell height exceeds row height - collapse a cell.
+ data.style.height = (newHeight - EXPANDER_HEIGHT) + "px";
+ expander.src = imgPath + "ellipses_light.gif";
+ CellsInfo[idx.group][i].expanded = false;
+ } else {
+ // Cell height is less then or equal to row height - expand a cell.
+ data.style.height = "";
+ expander.src = imgPath + "arrows_light.gif";
+ CellsInfo[idx.group][i].expanded = true;
+ }
+ }
+
+ if (mayNeedScroll) {
+ var idxStr = "_" + idx.group + "_" + idx.cell;
+ var clickedExpandableDiv = document.getElementById("cell" + idxStr);
+ // Scroll page up if a row is collapsed and the rows top is above the
+ // viewport. The amount of scroll is the difference between a new and old
+ // row height.
+ if (!isElemTopVisible(clickedExpandableDiv)) {
+ window.scrollBy(0, newHeight - cellInfo.height);
+ }
+ }
+}