xref: /aosp_15_r20/external/clang/www/analyzer/scripts/expandcollapse.js (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// expand/collapse button (expander) is added if height of a cell content
2*67e74705SXin Li// exceeds CLIP_HEIGHT px.
3*67e74705SXin Livar CLIP_HEIGHT = 135;
4*67e74705SXin Li
5*67e74705SXin Li// Height in pixels of an expander image.
6*67e74705SXin Livar EXPANDER_HEIGHT = 13;
7*67e74705SXin Li
8*67e74705SXin Li// Path to images for an expander.
9*67e74705SXin Livar imgPath = "./images/expandcollapse/";
10*67e74705SXin Li
11*67e74705SXin Li// array[group][cell] of { 'height', 'expanded' }.
12*67e74705SXin Li// group: a number; cells of the same group belong to the same table row.
13*67e74705SXin Li// cell: a number; unique index of a cell in a group.
14*67e74705SXin Li// height: a number, px; original height of a cell in a table.
15*67e74705SXin Li// expanded: boolean; is a cell expanded or collapsed?
16*67e74705SXin Livar CellsInfo = [];
17*67e74705SXin Li
18*67e74705SXin Li// Extracts group and cell indices from an id of the form identifier_group_cell.
19*67e74705SXin Lifunction getCellIdx(id) {
20*67e74705SXin Li  var idx = id.substr(id.indexOf("_") + 1).split("_");
21*67e74705SXin Li  return { 'group': idx[0], 'cell': idx[1] };
22*67e74705SXin Li}
23*67e74705SXin Li
24*67e74705SXin Li// Returns { 'height', 'expanded' } info for a cell with a given id.
25*67e74705SXin Lifunction getCellInfo(id) {
26*67e74705SXin Li  var idx = getCellIdx(id);
27*67e74705SXin Li  return CellsInfo[idx.group][idx.cell];
28*67e74705SXin Li}
29*67e74705SXin Li
30*67e74705SXin Li// Initialization, add nodes, collect info.
31*67e74705SXin Lifunction initExpandCollapse() {
32*67e74705SXin Li  if (!document.getElementById)
33*67e74705SXin Li    return;
34*67e74705SXin Li
35*67e74705SXin Li  var groupCount = 0;
36*67e74705SXin Li
37*67e74705SXin Li  // Examine all table rows in the document.
38*67e74705SXin Li  var rows = document.body.getElementsByTagName("tr");
39*67e74705SXin Li  for (var i=0; i<rows.length; i+=1) {
40*67e74705SXin Li
41*67e74705SXin Li    var cellCount=0, newGroupCreated = false;
42*67e74705SXin Li
43*67e74705SXin Li    // Examine all divs in a table row.
44*67e74705SXin Li    var divs = rows[i].getElementsByTagName("div");
45*67e74705SXin Li    for (var j=0; j<divs.length; j+=1) {
46*67e74705SXin Li
47*67e74705SXin Li      var expandableDiv = divs[j];
48*67e74705SXin Li
49*67e74705SXin Li      if (expandableDiv.className.indexOf("expandable") == -1)
50*67e74705SXin Li        continue;
51*67e74705SXin Li
52*67e74705SXin Li      if (expandableDiv.offsetHeight <= CLIP_HEIGHT)
53*67e74705SXin Li        continue;
54*67e74705SXin Li
55*67e74705SXin Li      // We found a div wrapping a cell content whose height exceeds
56*67e74705SXin Li      // CLIP_HEIGHT.
57*67e74705SXin Li      var originalHeight = expandableDiv.offsetHeight;
58*67e74705SXin Li      // Unique postfix for ids for generated nodes for a given cell.
59*67e74705SXin Li      var idxStr = "_" + groupCount + "_" + cellCount;
60*67e74705SXin Li      // Create an expander and an additional wrapper for a cell content.
61*67e74705SXin Li      //
62*67e74705SXin Li      //                                --- expandableDiv ----
63*67e74705SXin Li      //  --- expandableDiv ---         | ------ data ------ |
64*67e74705SXin Li      //  |    cell content   |   ->    | |  cell content  | |
65*67e74705SXin Li      //  ---------------------         | ------------------ |
66*67e74705SXin Li      //                                | ---- expander ---- |
67*67e74705SXin Li      //                                ----------------------
68*67e74705SXin Li      var data = document.createElement("div");
69*67e74705SXin Li      data.className = "data";
70*67e74705SXin Li      data.id = "data" + idxStr;
71*67e74705SXin Li      data.innerHTML = expandableDiv.innerHTML;
72*67e74705SXin Li      with (data.style) { height = (CLIP_HEIGHT - EXPANDER_HEIGHT) + "px";
73*67e74705SXin Li                          overflow = "hidden" }
74*67e74705SXin Li
75*67e74705SXin Li      var expander = document.createElement("img");
76*67e74705SXin Li      with (expander.style) { display = "block"; paddingTop = "5px"; }
77*67e74705SXin Li      expander.src = imgPath + "ellipses_light.gif";
78*67e74705SXin Li      expander.id = "expander" + idxStr;
79*67e74705SXin Li
80*67e74705SXin Li      // Add mouse calbacks to expander.
81*67e74705SXin Li      expander.onclick = function() {
82*67e74705SXin Li        expandCollapse(this.id);
83*67e74705SXin Li        // Hack for Opera - onmouseout callback is not invoked when page
84*67e74705SXin Li        // content changes dinamically and mouse pointer goes out of an element.
85*67e74705SXin Li        this.src = imgPath +
86*67e74705SXin Li                   (getCellInfo(this.id).expanded ? "arrows_light.gif"
87*67e74705SXin Li                                                  : "ellipses_light.gif");
88*67e74705SXin Li      }
89*67e74705SXin Li      expander.onmouseover = function() {
90*67e74705SXin Li        this.src = imgPath +
91*67e74705SXin Li                   (getCellInfo(this.id).expanded ? "arrows_dark.gif"
92*67e74705SXin Li                                                  : "ellipses_dark.gif");
93*67e74705SXin Li      }
94*67e74705SXin Li      expander.onmouseout = function() {
95*67e74705SXin Li        this.src = imgPath +
96*67e74705SXin Li                   (getCellInfo(this.id).expanded ? "arrows_light.gif"
97*67e74705SXin Li                                                  : "ellipses_light.gif");
98*67e74705SXin Li      }
99*67e74705SXin Li
100*67e74705SXin Li      expandableDiv.innerHTML = "";
101*67e74705SXin Li      expandableDiv.appendChild(data);
102*67e74705SXin Li      expandableDiv.appendChild(expander);
103*67e74705SXin Li      expandableDiv.style.height = CLIP_HEIGHT + "px";
104*67e74705SXin Li      expandableDiv.id = "cell"+ idxStr;
105*67e74705SXin Li
106*67e74705SXin Li      // Keep original cell height and its ecpanded/cpllapsed state.
107*67e74705SXin Li      if (!newGroupCreated) {
108*67e74705SXin Li        CellsInfo[groupCount] = [];
109*67e74705SXin Li        newGroupCreated = true;
110*67e74705SXin Li      }
111*67e74705SXin Li      CellsInfo[groupCount][cellCount] = { 'height' : originalHeight,
112*67e74705SXin Li                                           'expanded' : false };
113*67e74705SXin Li      cellCount += 1;
114*67e74705SXin Li    }
115*67e74705SXin Li    groupCount += newGroupCreated ? 1 : 0;
116*67e74705SXin Li  }
117*67e74705SXin Li}
118*67e74705SXin Li
119*67e74705SXin Lifunction isElemTopVisible(elem) {
120*67e74705SXin Li  var body = document.body,
121*67e74705SXin Li      html = document.documentElement,
122*67e74705SXin Li      // Calculate expandableDiv absolute Y coordinate from the top of body.
123*67e74705SXin Li      bodyRect = body.getBoundingClientRect(),
124*67e74705SXin Li      elemRect = elem.getBoundingClientRect(),
125*67e74705SXin Li      elemOffset = Math.floor(elemRect.top - bodyRect.top),
126*67e74705SXin Li      // Calculate the absoute Y coordinate of visible area.
127*67e74705SXin Li      scrollTop = html.scrollTop || body && body.scrollTop || 0;
128*67e74705SXin Li  scrollTop -= html.clientTop; // IE<8
129*67e74705SXin Li
130*67e74705SXin Li
131*67e74705SXin Li  if (elemOffset < scrollTop)
132*67e74705SXin Li    return false;
133*67e74705SXin Li
134*67e74705SXin Li  return true;
135*67e74705SXin Li}
136*67e74705SXin Li
137*67e74705SXin Li// Invoked when an expander is pressed; expand/collapse a cell.
138*67e74705SXin Lifunction expandCollapse(id) {
139*67e74705SXin Li  var cellInfo = getCellInfo(id);
140*67e74705SXin Li  var idx = getCellIdx(id);
141*67e74705SXin Li
142*67e74705SXin Li  // New height of a row.
143*67e74705SXin Li  var newHeight;
144*67e74705SXin Li  // Smart page scrolling may be done after collapse.
145*67e74705SXin Li  var mayNeedScroll;
146*67e74705SXin Li
147*67e74705SXin Li  if (cellInfo.expanded) {
148*67e74705SXin Li    // Cell is expanded - collapse the row height to CLIP_HEIGHT.
149*67e74705SXin Li    newHeight = CLIP_HEIGHT;
150*67e74705SXin Li    mayNeedScroll = true;
151*67e74705SXin Li  }
152*67e74705SXin Li  else {
153*67e74705SXin Li    // Cell is collapsed - expand the row height to the cells original height.
154*67e74705SXin Li    newHeight = cellInfo.height;
155*67e74705SXin Li    mayNeedScroll = false;
156*67e74705SXin Li  }
157*67e74705SXin Li
158*67e74705SXin Li  // Update all cells (height and expanded/collapsed state) in a row according
159*67e74705SXin Li  // to the new height of the row.
160*67e74705SXin Li  for (var i = 0; i < CellsInfo[idx.group].length; i++) {
161*67e74705SXin Li    var idxStr = "_" + idx.group + "_" + i;
162*67e74705SXin Li    var expandableDiv = document.getElementById("cell" + idxStr);
163*67e74705SXin Li    expandableDiv.style.height = newHeight + "px";
164*67e74705SXin Li    var data = document.getElementById("data" + idxStr);
165*67e74705SXin Li    var expander = document.getElementById("expander" + idxStr);
166*67e74705SXin Li    var state = CellsInfo[idx.group][i];
167*67e74705SXin Li
168*67e74705SXin Li    if (state.height > newHeight) {
169*67e74705SXin Li      // Cell height exceeds row height - collapse a cell.
170*67e74705SXin Li      data.style.height = (newHeight - EXPANDER_HEIGHT) + "px";
171*67e74705SXin Li      expander.src = imgPath + "ellipses_light.gif";
172*67e74705SXin Li      CellsInfo[idx.group][i].expanded = false;
173*67e74705SXin Li    } else {
174*67e74705SXin Li      // Cell height is less then or equal to row height - expand a cell.
175*67e74705SXin Li      data.style.height = "";
176*67e74705SXin Li      expander.src = imgPath + "arrows_light.gif";
177*67e74705SXin Li      CellsInfo[idx.group][i].expanded = true;
178*67e74705SXin Li    }
179*67e74705SXin Li  }
180*67e74705SXin Li
181*67e74705SXin Li  if (mayNeedScroll) {
182*67e74705SXin Li    var idxStr = "_" + idx.group + "_" + idx.cell;
183*67e74705SXin Li    var clickedExpandableDiv = document.getElementById("cell" + idxStr);
184*67e74705SXin Li    // Scroll page up if a row is collapsed and the rows top is above the
185*67e74705SXin Li    // viewport. The amount of scroll is the difference between a new and old
186*67e74705SXin Li    // row height.
187*67e74705SXin Li    if (!isElemTopVisible(clickedExpandableDiv)) {
188*67e74705SXin Li      window.scrollBy(0, newHeight - cellInfo.height);
189*67e74705SXin Li    }
190*67e74705SXin Li  }
191*67e74705SXin Li}
192