graph.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*##############################################################################
  2. # HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. ############################################################################## */
  16. var labelPopup = null;
  17. var popupWidth = 0;
  18. var popupHeight= 0;
  19. var popupTimerId = null;
  20. var prevWidth = 0;
  21. var prevHeight= 0;
  22. var processingPopup = false;
  23. function resize_graph(svg)
  24. {
  25. if (!svg)
  26. svg=document.getElementById('SVGGraph');
  27. if (!svg)
  28. return;
  29. var root=svg.getSVGDocument().rootElement;
  30. if (!root)
  31. return;
  32. var maxW = svg.offsetWidth;
  33. var maxH = svg.offsetHeight;
  34. if (Math.abs(maxW - prevWidth) < 100 && Math.abs(maxH - prevHeight) < 100)
  35. return;
  36. root.currentScale = 1;
  37. root.currentTranslate.x = 0;
  38. root.currentTranslate.y = 0;
  39. prevWidth = maxW;
  40. prevHeight = maxH;
  41. }
  42. function get_popup_div(popup_id)
  43. {
  44. var frame=document.frames['popupFrame'];
  45. if(!frame)
  46. return null;
  47. var div=frame.document.getElementById('popup_'+popup_id);
  48. if(!div)
  49. return null;
  50. if(div.length)
  51. return null; //multiple
  52. return div;
  53. }
  54. function show_popup(evt, popup_id,x,y)
  55. {
  56. if (processingPopup || !evt || !evt.shiftKey || evt.ctrlKey || evt.altKey)
  57. {
  58. processingPopup = false;
  59. return;
  60. }
  61. processingPopup = true;
  62. if (labelPopup)
  63. hide_popup();
  64. labelPopup = window.createPopup();
  65. var svg=document.getElementById('SVGGraph');
  66. if(!svg)
  67. {
  68. processingPopup = false;
  69. return;
  70. }
  71. if (!labelPopup.isOpen || window.top.activepopup != popup_id)
  72. {
  73. var div = get_popup_div(popup_id);
  74. if (!div)
  75. {
  76. processingPopup = false;
  77. return;
  78. }
  79. if(!x || !y)
  80. {
  81. var o=svg.getSVGDocument().getElementById(popup_id);
  82. if(!o)
  83. {
  84. processingPopup = false;
  85. return;
  86. }
  87. var root=svg.getSVGDocument().rootElement,
  88. scale=root.currentScale,
  89. shift=root.currentTranslate;
  90. var rect=o.getBBox();
  91. x=rect.x*scale+shift.x+rect.width*scale;
  92. y=rect.y*scale+shift.y+rect.height*scale;
  93. }
  94. window.top.activepopup=popup_id;
  95. stop_popup_timer();
  96. var popupBody=labelPopup.document.body;
  97. popupBody.style.border = "outset black 1px";
  98. popupBody.innerHTML=div.innerHTML;
  99. popupBody.style.overflow = "auto";
  100. popupBody.onmouseenter=stop_popup_timer;
  101. popupBody.onmouseleave=start_popup_timer;
  102. var tab = labelPopup.document.getElementById('tab');
  103. var link = labelPopup.document.getElementById('captionRow');
  104. link.style.display = 'block';
  105. labelPopup.show(2000,2000,640,480,null);
  106. popupWidth=tab.clientWidth+2,
  107. popupHeight=tab.clientHeight+2;
  108. if (popupWidth > screen.width)
  109. popupWidth = screen.width;
  110. if (popupHeight > screen.height)
  111. popupHeight = screen.height;
  112. }
  113. else
  114. {
  115. stop_popup_timer();
  116. start_popup_timer();
  117. processingPopup = false;
  118. return;
  119. }
  120. var xp=x+svg.offsetLeft-document.body.scrollLeft+window.screenLeft,
  121. yp=y+svg.offsetTop-document.body.scrollTop+window.screenTop;
  122. labelPopup.show(xp+5,yp+5,popupWidth,popupHeight,null);
  123. start_popup_timer();
  124. processingPopup = false;
  125. }
  126. function hide_popup()
  127. {
  128. stop_popup_timer();
  129. window.top.activepopup=null;
  130. if(labelPopup)
  131. {
  132. if (labelPopup.isOpen)
  133. labelPopup.hide();
  134. labelPopup=null;
  135. }
  136. }
  137. function start_popup_timer()
  138. {
  139. popupTimerId = setTimeout(hide_popup, 2000);//2 seconds
  140. }
  141. function stop_popup_timer()
  142. {
  143. if (popupTimerId)
  144. {
  145. clearTimeout(popupTimerId);
  146. popupTimerId = null;
  147. }
  148. }
  149. function load_svg(srcNode)
  150. {
  151. var svg=document.getElementById('SVGGraph');
  152. if(!svg)
  153. return null;
  154. var win=svg.getWindow();
  155. var doc = win.document;
  156. var srcRoot = srcNode.documentElement;
  157. var newsvg = win.parseXML(srcNode.text, doc);
  158. var root = doc.documentElement;
  159. //remove all existing children from root
  160. for (var child = root.firstChild; child; child = root.firstChild)
  161. root.removeChild(child);
  162. var width = srcRoot.getAttribute('width');
  163. if (width)
  164. root.setAttribute('width', width);
  165. var height = srcRoot.getAttribute('height')
  166. if (height)
  167. root.setAttribute('height', height);
  168. var viewBox = srcRoot.getAttribute('viewBox');
  169. if (viewBox)
  170. root.setAttribute('viewBox', viewBox);
  171. var children = newsvg.firstChild.childNodes;
  172. for (var i=0; i<children.length; i++)
  173. root.appendChild( children.item(i));
  174. return root;
  175. }
  176. function test_svg()
  177. {
  178. try
  179. {
  180. if(document.getElementById('SVGGraph').getAttribute('window'))
  181. {
  182. var re=/.*;\s*(\d+.\d*)/.exec(document.getElementById('SVGGraph').getSVGViewerVersion());
  183. if(re && re[1]>=3.0)
  184. return true;
  185. }
  186. }
  187. catch(e)
  188. {
  189. }
  190. document.getElementById('SVGLink').innerHTML='<br />You need Adobe&reg; SVG Viewer v3.0 to view graphs.'+
  191. 'It can be downloaded <a href="http://www.adobe.com/svg/viewer/install/">here</a>.<br />' +
  192. 'Adobe&reg; SVG Viewer is no longer supported by Adobe.<br />' +
  193. 'If you don&prime;t already have this software installed, please use GVC Graph Viewer Option';
  194. return false;
  195. }
  196. function showNodeOrEdgeDetails(popupId, graphName, wuid, queryName)
  197. {
  198. hide_popup();
  199. processingPopup = true;
  200. var win = window.open("about:blank", "_blank",
  201. "toolbar=no, location=no, directories=no, status=no, menubar=no" +
  202. ", scrollbars=yes, resizable=yes, width=640, height=300");
  203. if (!win)
  204. {
  205. alert("Popup window could not be opened! Please disable any popup killer and try again.");
  206. processingPopup = false;
  207. return;
  208. }
  209. var doc = win.document;
  210. var elementType = popupId.indexOf('_')== -1 ? 'Node':'Edge';
  211. var s = new Array();
  212. var i = 0;
  213. s[i++] = '<h3>Graph ';
  214. s[i++] = elementType;
  215. s[i++] = ' Information</h3>';
  216. var div = get_popup_div(popupId);
  217. if (!div || div.innerHTML.length==0)
  218. {
  219. s[i++] = '<table id="tab" style="font:menu;">';
  220. s[i++] = '<colgroup><col align="left" valign="top"/></colgroup>';
  221. if (wuid || queryName)
  222. {
  223. s[i++] = '<tr><th>';
  224. s[i++] = wuid ? 'workunit' : 'query';
  225. s[i++] = '</th><td>';
  226. s[i++] = wuid ? wuid : queryName;
  227. s[i++] = '</td></tr>';
  228. }
  229. if (graphName)
  230. {
  231. s[i++] = '<tr><th>graph</th><td>';
  232. s[i++] = graphName;
  233. s[i++] = '</td></tr>';
  234. }
  235. s[i++] = '<tr><th>id</th><td>';
  236. s[i++] = popupId;
  237. s[i++] = '</td></tr>';
  238. s[i++] = '<tr><th colspan="2">No additional information is available.</th></tr>';
  239. s[i++] = '</table>';
  240. doc.write( s.join('') );
  241. }
  242. else
  243. {
  244. s[i++] = div.innerHTML;
  245. doc.write( s.join('') );
  246. var row = doc.getElementById('wuRow');
  247. if (wuid && row.cells.length==2 && row.cells[1].innerText != '')
  248. row.style.display = 'block';
  249. if (graphName)
  250. {
  251. row = doc.getElementById('graphNameRow');
  252. row.style.display = 'block';
  253. }
  254. row = doc.getElementById('idRow');
  255. if (row)
  256. row.style.display = 'block';
  257. }
  258. doc.title = elementType + ' ' + popupId + graphName ? (' [' + graphName + ']'): '';
  259. processingPopup = false;
  260. }
  261. var tipsWnd = null;
  262. function showViewingTips()
  263. {
  264. if (tipsWnd)
  265. {
  266. tipsWnd.close();
  267. }
  268. var win = window.open( "about:blank", "_blank",
  269. "toolbar=0,location=0,directories=0,status=0,menubar=0," +
  270. "scrollbars=1, resizable=1, width=640, height=300");
  271. if (!win)
  272. {
  273. alert( "Popup window could not be opened! " +
  274. "Please disable any popup killer and try again.");
  275. }
  276. else
  277. {
  278. tipsWnd = win;
  279. var s = [];
  280. var i = 0;
  281. s[i++] = '<h3>Graph Viewing Tips</h3><table align="left"><colgroup>';
  282. s[i++] = '<col span="*" align="left"/></colgroup><tbody><tr><th>Pan</th>';
  283. s[i++] = '<th>:</th><td>Press Alt key and drag graph with the hand cursor</td>';
  284. s[i++] = '</tr><tr><th nowrap="true">Zoom In</th><th>:</th>';
  285. s[i++] = '<td>Press Ctrl key and click left mouse button</td></tr>';
  286. s[i++] = '<tr><th nowrap="true">Zoom Out</th><th>:</th>';
  287. s[i++] = '<td>Press Shift-Ctrl and click left mouse button</td></tr>';
  288. s[i++] = '<tr><th>Tooltips</th><th>:</th><td>Press Shift key while ';
  289. s[i++] = 'moving cursor over nodes and edges</td></tr><tr valign="top">';
  290. s[i++] = '<th nowrap="true">Increase size</th><th>:</th><td>Collapse ';
  291. s[i++] = 'left frame by dragging or clicking on separator.<br/>Toggle ';
  292. s[i++] = 'full screen view by pressing F11</td></tr><tr valign="top" ';
  293. s[i++] = 'style="border-bottom:gray 1px solid"><th>More</th><th>:</th>';
  294. s[i++] = '<td>The contex menu offers options like: Find, Copy SVG, View ';
  295. s[i++] = 'Source, Zoom In/Out, Save As, and Help</td></tr></tbody></table>';
  296. var doc = win.document.open("text/html", "replace");
  297. doc.write( s.join('') );
  298. doc.title = 'Graph Viewing Tips';
  299. }
  300. }
  301. function go(url)
  302. {
  303. document.location.href=url;
  304. }
  305. var prevFoundPolygon = null;
  306. var prevFill = null;
  307. function findGraphNode(id, svg)
  308. {
  309. if (id.length == 0) {
  310. alert("Please specify a node id to find in graph!");
  311. return;
  312. }
  313. var root = getGraphRoot(svg);
  314. if (!svg)
  315. svg=document.getElementById('SVGGraph');
  316. if (!svg)
  317. return;
  318. var root=svg.getSVGDocument().rootElement;
  319. if (!root)
  320. return;
  321. var node = root.getElementById(id);
  322. var polygon = null;
  323. if (node)
  324. {
  325. var links = node.getElementsByTagName('a');
  326. if (links.length)
  327. {
  328. polygons = links.item(0).getElementsByTagName('polygon');
  329. if (polygons.length)
  330. polygon = polygons.item(0);
  331. }
  332. }
  333. if (polygon != prevFoundPolygon && prevFoundPolygon)
  334. {
  335. if (prevFill == '')
  336. prevFoundPolygon.style.removeProperty('fill');
  337. else
  338. prevFoundPolygon.style.setProperty('fill', prevFill, "");
  339. prevFoundPolygon = null;
  340. }
  341. if (!polygon)
  342. {
  343. alert('Graph node not found!');
  344. resetFindGraphNode();
  345. }
  346. else
  347. if (polygon != prevFoundPolygon)
  348. {
  349. prevFoundPolygon = polygon;
  350. var textNodes = node.getElementsByTagName('text');
  351. if (textNodes.length > 0)
  352. {
  353. var firstChild = textNodes.item(0);
  354. var x = firstChild.getAttribute('x');
  355. var y = firstChild.getAttribute('y');
  356. //get svg plugin dimenstions
  357. var width = svg.offsetWidth;
  358. var height = svg.offsetHeight;
  359. //browser crashes if we zoom in too much so avoid it
  360. //
  361. //get graph dimensions
  362. var maxW = root.getAttribute('width') / 10;
  363. var maxH = root.getAttribute('height') / 10;
  364. width = Math.max(width, maxW);
  365. height = Math.max(height, maxH);
  366. var viewBox = (x-width/2) + ' ' + (y-height/2) + ' ' + width + ' ' + height;
  367. root.currentScale = 1;
  368. root.currentTranslate.x = 0;
  369. root.currentTranslate.y = 0;
  370. root.setAttribute('viewBox', viewBox);
  371. var resetFindBtn = document.getElementById('resetFindBtn');
  372. if (resetFindBtn)
  373. resetFindBtn.disabled = false;
  374. prevFill = polygon.style.getPropertyValue('fill');
  375. polygon.style.setProperty('fill' , 'yellow', "");
  376. }
  377. }
  378. }
  379. function getGraphRoot(svg)
  380. {
  381. if (!svg)
  382. svg=document.getElementById('SVGGraph');
  383. return svg ? svg.getSVGDocument().rootElement : null;
  384. }
  385. function resetFindGraphNode(svg)
  386. {
  387. var root = getGraphRoot(svg);
  388. if (root)
  389. {
  390. root.setAttribute('viewBox', '0 0 ' + root.getAttribute('width') + ' ' + root.getAttribute('height'));
  391. root.currentScale = 1;
  392. root.currentTranslate.x = 0;
  393. root.currentTranslate.y = 0;
  394. }
  395. if (prevFoundPolygon)
  396. {
  397. if (prevFill == '')
  398. prevFoundPolygon.style.removeProperty('fill');
  399. else
  400. prevFoundPolygon.style.setProperty('fill', prevFill, "")
  401. prevFoundPolygon = null;
  402. }
  403. var resetFindBtn = document.getElementById('resetFindBtn');
  404. if (resetFindBtn)
  405. resetFindBtn.disabled = true;
  406. }