TextGraph.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /****************************************************************
  2. ** Licensed Materials - Property of IBM
  3. **
  4. ** IBM Cognos Products: mdsrv
  5. **
  6. ** (C) Copyright IBM Corp. 2008, 2010
  7. **
  8. ** US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. *****************************************************************/
  10. //This object is used to create a table based 'graph' from the Graph object.
  11. //This provides a more detailed business view, and lets us meet accessability requirements, as the tables are readable by JAWS
  12. CTextGraph = function(Graph, lineageResponse)
  13. {
  14. this.Graph = Graph;
  15. this.lineageResponse = lineageResponse;
  16. this.GraphTables = {}; //tables to be written out
  17. this.GraphTableNames = {}; //set of table names so we can generate unique ids
  18. //turns camel case words back to human words, with spaces and everything!
  19. this.deCamelCaseWord = function(word)
  20. {
  21. if(word === undefined || word === null)
  22. {
  23. return "";
  24. }
  25. var res = "";
  26. for(var i = 0; i < word.length; i++)
  27. {
  28. var cur = word.charAt(i)
  29. if(i == 0) //recapitalize first letter
  30. res += cur.toLocaleUpperCase();
  31. else if(cur === cur.toLocaleUpperCase()) //if caps, then insert a space
  32. res += " " + cur;
  33. else //just copy the current character
  34. res += cur;
  35. }
  36. return res;
  37. }
  38. //add a table to this.GraphTables for the given node
  39. this.addTable = function(node)
  40. {
  41. this.GraphTables[node.nUniqueId] = {
  42. "node": node,
  43. "references": [],
  44. "queryItemReferences": [] //I'm not crazy about using an array and linearly processing it to get the query item refs, but it works and seems fast enough for now
  45. };
  46. this.GraphTableNames[node.modelObject.lineageObj.m_id] = true;
  47. }
  48. // add a reference (edge) to the table stored in this.GraphTables
  49. this.addReferenceToTable = function (connection)
  50. {
  51. var t = this.GraphTables[connection.m_left.nUniqueId];
  52. t["references"].push(connection.m_right);
  53. //try to get the gItem(Left|Right), but fall back to m_(left|right) if it's null
  54. var left = connection.gItemLeft === null ? connection.m_left : connection.gItemLeft;
  55. var right = connection.gItemRight === null ? connection.m_left : connection.gItemRight;
  56. if (left.modelObject.lineageObj.m_id != right.modelObject.lineageObj.m_id)
  57. t["queryItemReferences"].push([left.modelObject.lineageObj.m_id, right.modelObject.lineageObj.m_id])
  58. }
  59. //remove the duplicate elements from an array and return the array of unique elements
  60. this.removeDuplicates = function(array)
  61. {
  62. var results = [];
  63. var elementSet = {};
  64. var len = array.length;
  65. for( var i = 0; i < len; i++)
  66. {
  67. if (elementSet[array[i]] === undefined)
  68. {
  69. results.push(array[i]);
  70. elementSet[array[i]] = true;
  71. }
  72. }
  73. return results;
  74. }
  75. this.whitespaceToUnderscore = function(str)
  76. {
  77. var replaceWhitespace = /\s/gi;
  78. return str.replace(replaceWhitespace, '_');
  79. }
  80. // return a closure (function that saves initial state) that can be used to generate the table header
  81. // read http://en.wikipedia.org/wiki/Closure_%28computer_science%29 if you don't understand the concept
  82. this.createHeaderStringClosure = function(id)
  83. {
  84. var whitespaceToUnderscore = this.whitespaceToUnderscore; //save the function ref since the closures 'this' is different
  85. return function (str) {
  86. return whitespaceToUnderscore(id) + str + 'Header';
  87. }
  88. }
  89. //recursively process the child objects to generate the references and nested tables for the query items
  90. this.buildQueryItemTable = function(childObj, queryItemReferences, idPrefix, parentHeader)
  91. {
  92. var elementID = idPrefix + childObj.m_id;
  93. if( this.GraphTableNames[elementID] !== undefined )
  94. {
  95. elementID += "queryItem"
  96. }
  97. var summary = this.deCamelCaseWord(childObj.m_type) + ' ' + childObj.m_id;
  98. var str = '<table id="' + elementID + '" summary="' + summary + '"><caption class="ts">' + childObj.m_name + '</caption>';
  99. var properties = childObj.getProperties();
  100. var refs = childObj.getChildRefs().slice(0); //copy the child refs, since we don't want to overwrite the originals when we add the queryItemReferences
  101. var propertyValue = document.getElementById("propertyValue").innerHTML; //load the localized headings from original html
  102. var valueValue = document.getElementById("valueValue").innerHTML;
  103. var referencesValue = document.getElementById("referenceValue").innerHTML;
  104. var getHeaderString = this.createHeaderStringClosure(elementID);
  105. //because the levels will point to query item that might also be represented as a top level table, we need to prefix the references to
  106. //query items to make them unique
  107. if(childObj.getType() == "level")
  108. idPrefix += childObj.m_id + ".";
  109. for ( var i = 0; i < queryItemReferences.length; i++)
  110. {
  111. var cur = queryItemReferences[i];
  112. var name = cur[0];
  113. var id = childObj.m_id;
  114. if (name === id) //if this child object has the reference/add it to the references array
  115. refs.push(cur[1])
  116. }
  117. refs = this.removeDuplicates(refs);
  118. str += '<thead><tr><th class="header2" id="' + getHeaderString('Property') + '">' + propertyValue + '</th><th class="header2" id="' + getHeaderString('Value') + '">'+ valueValue +'</th></tr></thead>'
  119. for ( var i = 0; i < properties.length; i++ )
  120. {
  121. var prop = properties[i];
  122. var currentObjectHeader = getHeaderString(this.whitespaceToUnderscore(prop.m_name));
  123. str += '<th id="' + currentObjectHeader + '" class="header2" headers="' + getHeaderString('Property') + ' ' + parentHeader + '">' + prop.m_dispName + '</th><td class="dataCell" headers="' + currentObjectHeader + ' ' + getHeaderString('Value') + ' ' + parentHeader + '">' + prop.m_value + '</td></tr>';
  124. }
  125. var referenceHeader = getHeaderString(this.whitespaceToUnderscore(referencesValue));
  126. str += '<tr><th id="' + referenceHeader + '" class="header2" headers="' + getHeaderString('Property') + ' ' + parentHeader + '">' + referencesValue + '</th><td headers="' + referenceHeader + ' ' + getHeaderString('Value')+ ' ' + parentHeader + '">';
  127. if(refs.length > 0)
  128. str += '<ul class="referencesList">';
  129. for ( var i = 0; i < refs.length; i++ )
  130. {
  131. var ref = refs[i];
  132. //if this is a level datatype, it's references point to a query item, not a top level table
  133. var refId = childObj.getType() == "level" ? idPrefix + refs[i] : refs[i] ;
  134. str += '<li><a class="textGraphLink" href="#' + refId + '">' + ref + '</a></li>'//write the current reference
  135. }
  136. if(refs.length > 0)
  137. str += '</ul>'
  138. str += '</td><tr></table>'
  139. var recursiveRefs = childObj.getChildRefs(); //we really need to change this to use the "each" method if we ever drop IE 6
  140. for ( var i = 0; i < recursiveRefs.length; i++)
  141. {
  142. var ref = recursiveRefs[i];
  143. var child = this.lineageResponse.lookup(ref);
  144. str += this.buildQueryItemTable(child, queryItemReferences, idPrefix, parentHeader);
  145. }
  146. return str;
  147. }
  148. // iterate over the nodes in the list and output the contents to an HTML table at div "textgraph"
  149. this.writeGraphTablesToHTML = function()
  150. {
  151. var numNodes = this.Graph.m_nodeList.length;
  152. var propertyValue = document.getElementById("propertyValue").innerHTML; //load the localized headings from original html
  153. var valueValue = document.getElementById("valueValue").innerHTML;
  154. var referencesValue = document.getElementById("referenceValue").innerHTML;
  155. var queryItemValue = document.getElementById("queryItemValue").innerHTML;
  156. var contentsValue = document.getElementById("contentsValue").innerHTML;
  157. var TableString = '';
  158. var TableOfContents = '<h1 class="ta">' + contentsValue + '<ul id="tableOfContents">';
  159. //create a table for each node
  160. for ( var j = 0; j < numNodes; j++ )
  161. {
  162. var str = '';
  163. var obj = this.GraphTables[this.Graph.m_nodeList[j].nUniqueId].node.modelObject.lineageObj;
  164. var refs = this.removeDuplicates( this.GraphTables[this.Graph.m_nodeList[j].nUniqueId].references );
  165. var properties = obj.getProperties();
  166. var getHeaderString = this.createHeaderStringClosure(obj.m_id);
  167. //create rows for the current table
  168. for ( var i = 0; i < properties.length; i++ )
  169. {
  170. var prop = properties[i];
  171. var currentObjectHeader = getHeaderString(this.whitespaceToUnderscore(prop.m_name));
  172. str += '<tr><th id="' + currentObjectHeader + '" class="header2" headers="' + getHeaderString('Property')+ '">' + prop.m_dispName + '</th><td class="dataCell" headers="' + currentObjectHeader + ' ' + getHeaderString('Value') +'">' + prop.m_value + '</td>';
  173. }
  174. var referencesHeader = getHeaderString(this.whitespaceToUnderscore(referencesValue));
  175. str += '<tr><th id="' + referencesHeader + '" class="header2" headers="' + getHeaderString('Property') + '"> ' + referencesValue + '</th><td class="dataCell" headers="' + referencesHeader + ' ' + getHeaderString('Value') + '">';
  176. //write the list of references
  177. if(refs.length > 0)
  178. str += '<ul class="referencesList">';
  179. for (var i = 0; i < refs.length; i++)
  180. {
  181. var ref = refs[i];
  182. str += '<li><a href="#' + ref.modelObject.lineageObj.m_id + '">' + ref.modelObject.lineageObj.m_id + '</a></li>';
  183. }
  184. if(refs.length > 0)
  185. str += '</ul>';
  186. str += '</td></tr>'
  187. var childObjIds = obj.getChildRefs();
  188. var childTables = "";
  189. for ( var i = 0; i < childObjIds.length; i++)
  190. {
  191. var childObj = this.lineageResponse.lookup( childObjIds[i] );
  192. if(childObj) //lookup will return null in some cases, so we need to check this
  193. childTables += this.buildQueryItemTable(childObj, this.GraphTables[this.Graph.m_nodeList[j].nUniqueId].queryItemReferences, "", getHeaderString('QueryItems'));
  194. }
  195. //add reference to table of contents
  196. TableOfContents += '<li><a href="#' + obj.m_id +'">' + obj.m_id + '</a></li>';
  197. //create table
  198. var summary = this.deCamelCaseWord(obj.m_type) + ' ' + obj.m_id;
  199. TableString += '<table class="businessViewRootTable" id="' + obj.m_id + '" summary="' + summary + '"><caption class="ts">' + obj.m_id + '</caption><thead><tr><th class="header2" id="' + getHeaderString('Property') + '">' + propertyValue + '</th><th class="header2" id="' + getHeaderString('Value') + '">'+ valueValue +'</th></tr></thead><tbody>' + str;
  200. TableString += '<tr><th class="header2" id="' + getHeaderString('QueryItems') + '" headers="' + getHeaderString('Property')+ '">' + queryItemValue + '</th><td class="dataCell" headers="' + getHeaderString('QueryItems') + ' ' + getHeaderString('Value') +'">' + childTables + '</td></tr></tbody></table>';
  201. }
  202. TableOfContents += '</ul></h1>';
  203. //write table to the DOM
  204. document.getElementById("textgraph").innerHTML = TableOfContents + TableString;
  205. }
  206. //generate the tables and write them to the page
  207. this.Init = function()
  208. {
  209. var numNodes = this.Graph.m_nodeList.length;
  210. for ( var j = 0; j < numNodes; j++ )
  211. {
  212. this.addTable(this.Graph.m_nodeList[j])
  213. }
  214. var numConnections = this.Graph.m_connectionList.length;
  215. for ( var i = 0; i < numConnections; i++ )
  216. {
  217. this.addReferenceToTable(this.Graph.m_connectionList[i]);
  218. }
  219. this.writeGraphTablesToHTML();
  220. LNS.replaceBlankTableCells(document.getElementById('id_business_view'));
  221. }
  222. }