diff options
Diffstat (limited to 'www/analyzer/scripts/expandcollapse.js')
-rw-r--r-- | www/analyzer/scripts/expandcollapse.js | 191 |
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); + } + } +} |