xtabCache.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. // Licensed Materials - Property of IBM
  2. //
  3. // IBM Cognos Products: pps
  4. //
  5. // (C) Copyright IBM Corp. 2005, 2017
  6. //
  7. // US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  8. var xtabCache;
  9. //A class responsible for maintaining and providing access to crosstab elements
  10. function xtabCache() {
  11. //**********************
  12. //Data members
  13. /* private */ xtabCells = new Array();
  14. /* private */ xtabLevelSelectors = new Array();
  15. xtabLevelSelectors["r"] = new Array();
  16. xtabLevelSelectors["c"] = new Array();
  17. /* private */ CLASS_HEADER_MOUSE_OVER = "header-mouse-over";
  18. /* private */ CLASS_CELL_SELECTED = "cell-selected";
  19. /* private */ CLASS_CELL_INTER_SELECTED = "cell-intersection-selected";
  20. /* private */ CLASS_HEADER_SELECTED = "header-selected";
  21. /* private */ CLASS_LEVEL_SELECTED = "level-selected";
  22. /* private */ CLASS_CHART_LEGEND_CELL_SELECTED = "chart-legend-cell-selected";
  23. /* private */ CLASS_CHART_LEGEND_LAST_CELL_SELECTED = "chart-legend-last-cell-selected"
  24. /* private */ CLASS_LEVEL_DRAG_OVER = "level-drag-over";
  25. /* private */ CLASS_LEVEL_AREA_SELECTED = "level-area-selected";
  26. /* public */ this.initialized = false;
  27. //**********************
  28. //Private Methods
  29. function cacheObj(obj) {
  30. if (obj.getAttribute && obj.getAttribute("type")) {
  31. var type = obj.getAttribute("type");
  32. if (type == "d" || type == "r" || type == "c") {
  33. var row = parseRowId(obj.id);
  34. var col = parseColId(obj.id);
  35. if (!exists(row,col)) {
  36. initClassName(obj);
  37. if ((type == "r" || type == "c") && obj.firstChild.setAttribute) {
  38. initClassName(obj.firstChild);
  39. }
  40. if (xtabCells[parseInt(row)] == null)
  41. xtabCells[parseInt(row)] = new Array();
  42. if (type != "d") {
  43. obj.setAttribute("selected","0");
  44. obj.setAttribute("dragover","0");
  45. }
  46. xtabCells[parseInt(row)][parseInt(col)] = obj;
  47. }
  48. } else if (type.indexOf("lr") >= 0 || type.indexOf("lc") >= 0) {
  49. initClassName(obj);
  50. xtabLevelSelectors[obj.id.charAt(1)][parseInt(obj.id.substr(2))] = obj;
  51. }
  52. }
  53. }
  54. function initClassName(obj) {
  55. if (obj.className)
  56. obj.setAttribute("unSelectedClassName",obj.className);
  57. else
  58. obj.setAttribute("unSelectedClassName","");
  59. }
  60. function processNode(node) {
  61. cacheObj(node);
  62. var child = node.firstChild;
  63. while (child != null) {
  64. processNode(child);
  65. child = child.nextSibling;
  66. }
  67. }
  68. //**********************
  69. //Initialize Method
  70. //Walk the element given and cache any level selection or cell children
  71. this.initialize = function(xtab) {
  72. if (xtab)
  73. processNode(xtab);
  74. this.initialized = true;
  75. }
  76. //**********************
  77. //Public methods and helper functions
  78. this.getXtabCell = function(row,col) {
  79. if (xtabCells[parseInt(row)] && xtabCells[parseInt(row)][parseInt(col)])
  80. return xtabCells[parseInt(row)][parseInt(col)];
  81. else {
  82. //Caching missed this one, so reconstruct the ID and get it the slow way
  83. return document.getElementById(row + "-" + col);
  84. }
  85. }
  86. this.getXtabLevelSelector = function(rc,level) {
  87. if (xtabLevelSelectors[rc][parseInt(level)])
  88. return xtabLevelSelectors[rc][parseInt(level)];
  89. else
  90. //Caching missed this one, so reconstruct the ID and get it the slow way
  91. return document.getElementById("l" + rc + level);
  92. }
  93. //The following methods select the row/cols in the xtab.
  94. //They rely on the underlying data structure to make things as efficient as possible
  95. //We also assume that the cells given exist, and are cached.
  96. function exists(row,col) {
  97. return (xtabCells[row] != null && xtabCells[row][col] != null);
  98. }
  99. this.exists = exists;
  100. function getRowHeader(row) {
  101. if (exists(row,numRowLevels - 1))
  102. return xtabCells[row][numRowLevels - 1];
  103. else {
  104. var col = numRowLevels - 2;
  105. while (!exists(row,col)) {
  106. col--;
  107. if (col < 0)
  108. return null;
  109. }
  110. return xtabCells[row][col];
  111. }
  112. }
  113. this.getRowHeader = getRowHeader;
  114. function getColHeader(col) {
  115. if (exists(numColLevels - 1,col))
  116. return xtabCells[numColLevels - 1][col];
  117. else {
  118. var row = numColLevels - 2;
  119. while (!exists(row,col)) {
  120. row--;
  121. if (row < 0)
  122. return null;
  123. }
  124. return xtabCells[row][col];
  125. }
  126. }
  127. this.getColHeader = getColHeader;
  128. function numberSelectedInRow(row) {
  129. return parseInt(getRowHeader(row).getAttribute("selected"));
  130. }
  131. function numberSelectedInColumn(col) {
  132. return parseInt(getColHeader(col).getAttribute("selected"));
  133. }
  134. function isACellInRowSelected(row) {
  135. return (getRowHeader(row).getAttribute("selected") != "0");
  136. }
  137. function isACellInColumnSelected(col) {
  138. return (getColHeader(col).getAttribute("selected") != "0");
  139. }
  140. this.isRowSelected = function(row) {
  141. return (isACellInRowSelected(row));
  142. }
  143. this.isColSelected = function(col) {
  144. return (isACellInColumnSelected(col));
  145. }
  146. this.selectRow = function(row,col,selecting) {
  147. row = parseInt(row);
  148. col = parseInt(col);
  149. //Obtain the start and ending row numbers;
  150. rowHeader = xtabCells[row][col];
  151. var startRow = row;
  152. var endRow = startRow + 1;
  153. if(!rowHeader.getAttribute("summary"))
  154. while(endRow < maxRowID && (!exists(endRow,col)))
  155. endRow++;
  156. //Loop throught each row header and select all cached cells
  157. for (var i = startRow; i < endRow; i++) {
  158. if (getRowHeader(i)) {
  159. for (var j = col; j < numRowLevels; j++)
  160. if (exists(i,j))
  161. selectRowColHeader(i,j,selecting);
  162. if ((selecting && numberSelectedInRow(i) == 1) || (!selecting && !isACellInRowSelected(i))) {
  163. //Display the sort icon
  164. var rowHeader = getRowHeader(i);
  165. if (selecting)
  166. showSortState(rowHeader,rowHeader.getAttribute("type"));
  167. else
  168. hideSortIcon(rowHeader,rowHeader.getAttribute("type"));
  169. //loop throught each cell in the row
  170. for (var j = numRowLevels; j < maxColID; j++)
  171. if (exists(i,j))
  172. selectRowCell(i,j,selecting);
  173. }
  174. }
  175. }
  176. }
  177. function selectRowColHeader(row,col,selecting) {
  178. if (selecting) {
  179. xtabCells[row][col].setAttribute("selected",parseInt(xtabCells[row][col].getAttribute("selected")) + 1);
  180. if (parseInt(xtabCells[row][col].getAttribute("selected")) == 1)
  181. switchRowColHeaderCell(xtabCells[row][col]," " + CLASS_HEADER_SELECTED);
  182. } else {
  183. xtabCells[row][col].setAttribute("selected",parseInt(xtabCells[row][col].getAttribute("selected")) - 1);
  184. if (parseInt(xtabCells[row][col].getAttribute("selected")) == 0)
  185. switchRowColHeaderCell(xtabCells[row][col],"");
  186. }
  187. }
  188. function switchRowColHeaderCell(obj,classExt) {
  189. //If this obj is a row, then we are dealing with a chart legend
  190. //and must set the class of each cell in the row.
  191. if (obj.tagName == "TR") {
  192. switchChartLegendCells(obj,classExt);
  193. } else {
  194. obj.className = obj.getAttribute("unSelectedClassName") + classExt;
  195. //For row.col headers apply the style to the inner table (first child) as well.
  196. //To ensure that the CSS inheritance is passed into the table element
  197. var kid = obj.firstChild;
  198. if (kid.getAttribute)
  199. kid.className = kid.getAttribute("unSelectedClassName") + classExt;
  200. }
  201. }
  202. function switchChartLegendCells(obj, classExt) {
  203. //Skip the first cell
  204. //Switch each other cell
  205. var kid = obj.firstChild.nextSibling;
  206. while (kid) {
  207. if (!kid.getAttribute("unSelectedClassName"))
  208. initClassName(kid);
  209. if (classExt == "")
  210. kid.className = kid.getAttribute("unSelectedClassName");
  211. else
  212. if (kid == obj.firstChild.nextSibling)
  213. kid.className = classExt + " " + CLASS_CHART_LEGEND_CELL_SELECTED;
  214. else
  215. kid.className = classExt + " " + CLASS_CHART_LEGEND_LAST_CELL_SELECTED;
  216. kid = kid.nextSibling;
  217. }
  218. }
  219. function selectRowCell(row,col,selecting) {
  220. if (selecting) {
  221. if (isACellInColumnSelected(col)) {
  222. xtabCells[row][col].className = xtabCells[row][col].getAttribute("unSelectedClassName") + " " + CLASS_CELL_INTER_SELECTED;
  223. } else {
  224. xtabCells[row][col].className = xtabCells[row][col].getAttribute("unSelectedClassName") + " " + CLASS_CELL_SELECTED;
  225. }
  226. } else {
  227. if (isACellInColumnSelected(col)) {
  228. xtabCells[row][col].className = xtabCells[row][col].getAttribute("unSelectedClassName") + " " + CLASS_CELL_SELECTED;
  229. } else {
  230. xtabCells[row][col].className = xtabCells[row][col].getAttribute("unSelectedClassName");
  231. }
  232. }
  233. }
  234. this.selectCol = function(row,col,selecting) {
  235. row = parseInt(row);
  236. col = parseInt(col);
  237. //Obtain the start and ending col numbers;
  238. colHeader = xtabCells[row][col];
  239. var startCol = col;
  240. var endCol = startCol + 1;
  241. if(!colHeader.getAttribute("summary"))
  242. while(endCol < maxColID && (!exists(row,endCol)))
  243. endCol++;
  244. //Loop throught each row and select all cached cells
  245. for (var i = startCol; i < endCol; i++) {
  246. if (getColHeader(i)) {
  247. for (var j = row; j < numColLevels; j++)
  248. if (exists(j,i))
  249. selectRowColHeader(j,i,selecting);
  250. if ((selecting && numberSelectedInColumn(i) == 1) || (!selecting && !isACellInColumnSelected(i))) {
  251. //Display the sort icon
  252. var colHeader = getColHeader(i);
  253. if (selecting)
  254. showSortState(colHeader,colHeader.getAttribute("type"));
  255. else
  256. hideSortIcon(colHeader,colHeader.getAttribute("type"));
  257. //loop throught each cell in the column
  258. for (var j = numColLevels; j < maxRowID; j++)
  259. if (exists(j,i)) {
  260. selectColumnCell(j,i,selecting);
  261. }
  262. }
  263. }
  264. }
  265. }
  266. function selectColumnCell(row,col,selecting) {
  267. if (selecting) {
  268. if (isACellInRowSelected(row)) {
  269. xtabCells[row][col].className = xtabCells[row][col].getAttribute("unSelectedClassName") + " " + CLASS_CELL_INTER_SELECTED;
  270. } else {
  271. xtabCells[row][col].className = xtabCells[row][col].getAttribute("unSelectedClassName") + " " + CLASS_CELL_SELECTED;
  272. }
  273. } else {
  274. if (isACellInRowSelected(row)) {
  275. xtabCells[row][col].className = xtabCells[row][col].getAttribute("unSelectedClassName") + " " + CLASS_CELL_SELECTED;
  276. } else {
  277. xtabCells[row][col].className = xtabCells[row][col].getAttribute("unSelectedClassName");
  278. }
  279. }
  280. }
  281. this.selectLevel = function(rc,level,selecting) {
  282. level = parseInt(level);
  283. selectLevelSelector (rc, level, selecting);
  284. if (rc == "r") {
  285. for (var i = numColLevels; i < maxRowID; i++) {
  286. if (exists(i,level))
  287. selectLevelCell(i,level,selecting);
  288. }
  289. } else {
  290. for (var i = numRowLevels; i < maxColID; i++) {
  291. if (exists(level,i))
  292. selectLevelCell(level,i,selecting);
  293. }
  294. }
  295. }
  296. function selectLevelSelector (rc, level, selecting) {
  297. if (selecting) {
  298. //Only if this is not a chart legend
  299. if (xtabLevelSelectors[rc][parseInt(level)].className != "legend")
  300. xtabLevelSelectors[rc][parseInt(level)].className = xtabLevelSelectors[rc][parseInt(level)].getAttribute("unSelectedClassName") + " " + CLASS_LEVEL_AREA_SELECTED;
  301. } else {
  302. xtabLevelSelectors[rc][parseInt(level)].className = xtabLevelSelectors[rc][parseInt(level)].getAttribute("unSelectedClassName");
  303. }
  304. }
  305. function selectLevelCell (row,col,selecting) {
  306. if (selecting) {
  307. xtabCells[row][col].setAttribute("selected",1);
  308. switchRowColHeaderCell(xtabCells[row][col]," " + CLASS_LEVEL_SELECTED);
  309. } else {
  310. xtabCells[row][col].setAttribute("selected",0);
  311. switchRowColHeaderCell(xtabCells[row][col],"");
  312. }
  313. }
  314. this.dragOverLevel = function (rc,level,selecting) {
  315. level = parseInt(level);
  316. selectLevelSelector (rc, level, false);
  317. if (rc == "r") {
  318. for (var i = numColLevels; i < maxRowID; i++) {
  319. if (exists(i,level))
  320. selectDragLevelCell(i,level,selecting);
  321. }
  322. } else {
  323. for (var i = numRowLevels; i < maxColID; i++) {
  324. if (exists(level,i))
  325. selectDragLevelCell(level,i,selecting);
  326. }
  327. }
  328. }
  329. this.mouseOverHeader = function(row,col,selecting) {
  330. row = parseInt(row);
  331. col = parseInt(col);
  332. if (parseInt(xtabCells[row][col].getAttribute("selected")) == 0 && parseInt(xtabCells[row][col].getAttribute("dragover")) == 0) {
  333. if (selecting) {
  334. switchRowColHeaderCell(xtabCells[row][col]," " + CLASS_HEADER_MOUSE_OVER);
  335. } else {
  336. switchRowColHeaderCell(xtabCells[row][col],"");
  337. }
  338. }
  339. }
  340. function selectDragLevelCell (row,col,selecting) {
  341. if (selecting) {
  342. xtabCells[row][col].setAttribute("dragover","1");
  343. switchRowColHeaderCell(xtabCells[row][col]," " + CLASS_LEVEL_DRAG_OVER);
  344. } else {
  345. xtabCells[row][col].setAttribute("dragover","0");
  346. switchRowColHeaderCell(xtabCells[row][col],"");
  347. }
  348. }
  349. this.getRowColHeaderParent = function(row,col) {
  350. var type = xtabCells[row][col].getAttribute("type");
  351. if (type.charAt(0) == "r" && row) {
  352. var i = row;
  353. while (!xtabCells[i] || !xtabCells[i][col - 1])
  354. i--;
  355. return xtabCells[i][col - 1];
  356. } else if (type.charAt(0) == "c" && col) {
  357. var i = col;
  358. while (!xtabCells[row - 1][i])
  359. i--;
  360. return xtabCells[row - 1][i];
  361. }
  362. return null;
  363. }
  364. this.getNextRowColHeaderSibling = function(row,col) {
  365. var type = xtabCells[row][col].getAttribute("type");
  366. if (type.charAt(0) == "r" && row) {
  367. var therow = parseInt(row) + 1;
  368. while(therow < maxRowID) {
  369. if (exists(therow,col))
  370. return xtabCells[therow][col];
  371. therow++;
  372. }
  373. } else if (type.charAt(0) == "c" && col) {
  374. var thecol = parseInt(col) + 1;
  375. while(thecol < maxColID) {
  376. if (exists(row,thecol))
  377. return xtabCells[row][thecol];
  378. thecol++;
  379. }
  380. }
  381. return null;
  382. }
  383. }
  384. function isBottomDimension(obj) {
  385. var level = parseInt(obj.getAttribute("level"));
  386. var rc = obj.getAttribute("type");
  387. var dimIdx = obj.getAttribute("dimIdx");
  388. var bottomLevel = true;
  389. while (bottomLevel && xtabCache.getXtabLevelSelector(rc,level)) {
  390. if (xtabCache.getXtabLevelSelector(rc,level).getAttribute("dimIdx") != dimIdx) {
  391. bottomLevel = false;
  392. } else
  393. level++;
  394. }
  395. return bottomLevel;
  396. }
  397. function isOnlyDimensioninAxis(obj) {
  398. var rc = obj.getAttribute("type");
  399. var dimIdx = obj.getAttribute("dimIdx");
  400. var level = 0;
  401. var onlyDimension = true;
  402. while (onlyDimension && xtabCache.getXtabLevelSelector(rc,level)) {
  403. if (xtabCache.getXtabLevelSelector(rc,level).getAttribute("dimIdx") != dimIdx) {
  404. onlyDimension = false;
  405. } else
  406. level++;
  407. }
  408. return onlyDimension;
  409. }