go-init.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. function initGo() {
  2. if(!document.getElementById("myDiagramDiv")
  3. ||!document.getElementById("mySavedModel")
  4. ||!document.getElementsByName("highlight")){
  5. console.error("缺少元素 myDiagramDiv 或 mySavedModel 或 highlight");
  6. return;
  7. }
  8. var $ = go.GraphObject.make; // for conciseness in defining templates
  9. myDiagram =
  10. $(go.Diagram, "myDiagramDiv", // Diagram refers to its DIV HTML element by id
  11. {
  12. //maxSelectionCount: 1 ,// 一次只能选择一个元素no more than 1 element can be selected at a time
  13. isReadOnly: true,
  14. "toolManager.mouseWheelBehavior":go.ToolManager.WheelNone//鼠标滚轮事件禁止
  15. });
  16. // 为了简化代码,我们定义了一个函数来创建内容目录按钮To simplify this code we define a function for creating a context menu button:
  17. function makeButton(text, action, visiblePredicate) {
  18. return $("ContextMenuButton",
  19. $(go.TextBlock, text),
  20. {click: action},
  21. // 如果没有断定,不要被捆绑GraphObject.visible所干扰。don't bother with binding GraphObject.visible if there's no predicate
  22. visiblePredicate ? new go.Binding("visible", "", function (o, e) {
  23. return o.diagram ? visiblePredicate(o, e) : false;
  24. }).ofObject() : {});
  25. }
  26. function nodeInfo(d) { // Tooltip info for a node data object
  27. var str = "Node " + d.key + ": " + d.text + "\n";
  28. if (d.group)
  29. str += "member of " + d.group;
  30. else
  31. str += "top-level node";
  32. return str;
  33. }
  34. // 为节点定义外观与行为Define the appearance and behavior for Nodes:
  35. // 首先定义节点、连线与组群共用的内容目录First, define the shared context menu for all Nodes, Links, and Groups.
  36. // define the node template
  37. myDiagram.nodeTemplate =
  38. $(go.Node, "Auto",
  39. new go.Binding("location").makeTwoWay(),
  40. {
  41. locationSpot: go.Spot.Center,
  42. toEndSegmentLength: 30, fromEndSegmentLength: 30
  43. },
  44. $(go.Shape, "RoundedRectangle",
  45. {
  46. name: "OBJSHAPE",
  47. fill: "white",
  48. //desiredSize: new go.Size(30, 30)
  49. portId: "", cursor: "pointer", // 轮廓是端口,而不是整个节点the Shape is the port, not the whole Node
  50. // 允许出发和指向此端口的各种链接allow all kinds of links from and to this port
  51. fromLinkable: true, fromLinkableSelfNode: true, fromLinkableDuplicates: true,
  52. toLinkable: true, toLinkableSelfNode: true, toLinkableDuplicates: true
  53. }),
  54. $("HyperlinkText",
  55. function (node) {
  56. return node.data.url;
  57. },
  58. $(go.Panel, "Auto",
  59. $(go.TextBlock,
  60. {
  61. font: "bold 11pt helvetica, bold arial, sans-serif",
  62. editable: true // editing the text automatically updates the model data
  63. },
  64. new go.Binding("text", "text").makeTwoWay()))), // 标签显示节点数据的文本the label shows the node data's text
  65. {
  66. toolTip: // 为显示其信息的每个节点定义工具提示define a tooltip for each node that displays its information
  67. $("ToolTip",
  68. $(go.TextBlock, {margin: 4},
  69. new go.Binding("text", "", nodeInfo))
  70. )
  71. }
  72. );
  73. function linkInfo(d) { // 链接数据对象的工具提示信息Tooltip info for a link data object
  74. return "Link:\nfrom " + d.from + " to " + d.to;
  75. }
  76. // define the link template
  77. myDiagram.linkTemplate =
  78. $(go.Link,
  79. {routing: go.Link.AvoidsNodes,corner: 10 },
  80. {
  81. selectionAdornmentTemplate:
  82. $(go.Adornment,
  83. $(go.Shape,
  84. {isPanelMain: true, stroke: "dodgerblue", strokeWidth: 3}),
  85. $(go.Shape,
  86. {toArrow: "Standard", fill: "dodgerblue", stroke: null, scale: 1})
  87. ),
  88. adjusting: go.Link.Stretch,
  89. reshapable: true, relinkableFrom: true, relinkableTo: true,
  90. toShortLength: 2,
  91. relinkableFrom: true,
  92. relinkableTo: true
  93. },
  94. new go.Binding("points").makeTwoWay(),
  95. new go.Binding("curviness"),
  96. $(go.Shape, // the link shape
  97. {name: "OBJSHAPE"}),
  98. $(go.Shape, // the arrowhead
  99. {name: "ARWSHAPE", toArrow: "Standard"}),
  100. $("HyperlinkText",
  101. function (node) {
  102. return node.data.url;
  103. },
  104. $(go.Panel, "Auto",
  105. $(go.TextBlock,
  106. {
  107. font: "bold 11pt helvetica, bold arial, sans-serif",
  108. editable: true // editing the text automatically updates the model data
  109. },
  110. new go.Binding("text", "text").makeTwoWay()))), // 标签显示节点数据的文本the label shows the node data's text
  111. {
  112. toolTip: // define a tooltip for each link that displays its information
  113. $("ToolTip",
  114. $(go.TextBlock, {margin: 4},
  115. new go.Binding("text", "", getInfo))
  116. )
  117. }
  118. );
  119. // define the group template
  120. myDiagram.groupTemplate =
  121. $(go.Group, "Vertical",
  122. {
  123. selectionObjectName: "PANEL", // 选择控制柄围绕形状,而不是标签selection handle goes around shape, not label
  124. ungroupable: true, // 启用Ctrl-Shift-G以取消选定组的分组enable Ctrl-Shift-G to ungroup a selected Group
  125. selectionAdornmentTemplate: // adornment when a group is selected
  126. $(go.Adornment, "Auto",
  127. $(go.Shape, "Rectangle",
  128. {fill: null, stroke: "dodgerblue", strokeWidth: 3}),
  129. $(go.Placeholder)
  130. ),
  131. toSpot: go.Spot.AllSides, // links coming into groups at any side
  132. toEndSegmentLength: 30, fromEndSegmentLength: 30
  133. },
  134. $(go.Panel, "Auto",
  135. $(go.Shape, "Rectangle",
  136. {
  137. name: "OBJSHAPE",
  138. parameter1: 14,
  139. fill: "rgba(255,0,0,0.10)",
  140. // 允许从和到此端口的各种链接allow all kinds of links from and to this port
  141. portId: "", cursor: "pointer", // 轮廓是端口,而不是整个节点the Shape is the port, not the whole Node
  142. fromLinkable: true, fromLinkableSelfNode: true, fromLinkableDuplicates: true,
  143. toLinkable: true, toLinkableSelfNode: true, toLinkableDuplicates: true
  144. },
  145. new go.Binding("desiredSize", "ds")),
  146. $(go.Placeholder,
  147. {padding: 16, margin: 10, background: "transparent"}) // 表示成员所在的位置represents where the members are)
  148. ),
  149. $(go.TextBlock,
  150. {
  151. name: "GROUPTEXT",
  152. alignment: go.Spot.TopLeft,
  153. alignmentFocus: new go.Spot(0, 0, -4, -4),
  154. font: "Bold 10pt Sans-Serif",
  155. isMultiline: false, // 不允许在文本中使用换行符don't allow newlines in text
  156. editable: true // 允许用户进行就地编辑allow in-place editing by user
  157. },
  158. new go.Binding("text", "text")),
  159. {
  160. toolTip: // define a tooltip for each group that displays its information
  161. $("ToolTip",
  162. $(go.TextBlock, {margin: 4},
  163. new go.Binding("text", "", getInfo))
  164. )
  165. }
  166. );
  167. // add nodes, including groups, and links to the model
  168. // whenever selection changes, run updateHighlights
  169. myDiagram.addDiagramListener("ChangedSelection",
  170. function () {
  171. updateHighlights(getRadioButton());
  172. });
  173. myDiagram.select(myDiagram.findNodeForKey('A'));
  174. load();
  175. }
  176. function load() {
  177. myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
  178. }
  179. // This highlights all graph objects that should be highlighted
  180. // whenever a radio button is checked or selection changes.
  181. // Parameter e is the checked radio button.
  182. function updateHighlights(e) {
  183. // Set highlight to 0 for everything before updating
  184. myDiagram.nodes.each(function (node) {
  185. node.highlight = 0;
  186. });
  187. myDiagram.links.each(function (link) {
  188. link.highlight = 0;
  189. });
  190. // Get the selected GraphObject and run the appropriate method
  191. var sel = myDiagram.selection.first();
  192. if (sel !== null) {
  193. switch (e.id) {
  194. case "linksIn":
  195. linksTo(sel, 1);
  196. break;
  197. case "linksOut":
  198. linksFrom(sel, 1);
  199. break;
  200. case "linksAll":
  201. linksAll(sel, 1);
  202. break;
  203. case "nodesIn":
  204. nodesTo(sel, 1);
  205. break;
  206. case "nodesOut":
  207. nodesFrom(sel, 1);
  208. break;
  209. case "nodesConnect":
  210. nodesConnect(sel, 1);
  211. break;
  212. case "nodesReach":
  213. nodesReach(sel, 1);
  214. break;
  215. case "group":
  216. containing(sel, 1);
  217. break;
  218. case "groupsAll":
  219. containingAll(sel, 1);
  220. break;
  221. case "nodesMember":
  222. childNodes(sel, 1);
  223. break;
  224. case "nodesMembersAll":
  225. allMemberNodes(sel, 1);
  226. break;
  227. case "linksMember":
  228. childLinks(sel, 1);
  229. break;
  230. case "linksMembersAll":
  231. allMemberLinks(sel, 1);
  232. break;
  233. }
  234. }
  235. // Give everything the appropriate highlighting ( color and width of stroke )
  236. // nodes, including groups
  237. myDiagram.nodes.each(function (node) {
  238. var shp = node.findObject("OBJSHAPE");
  239. var grp = node.findObject("GROUPTEXT");
  240. var hl = node.highlight;
  241. highlight(shp, grp, hl);
  242. });
  243. // links
  244. myDiagram.links.each(function (link) {
  245. var hl = link.highlight;
  246. var shp = link.findObject("OBJSHAPE");
  247. var arw = link.findObject("ARWSHAPE");
  248. highlight(shp, arw, hl);
  249. });
  250. }
  251. // Functions for highlighting, called by updateHighlights.
  252. // x in each case is the selected object or the object being treated as such.
  253. // Some have return values for use by each other or for tooltips.
  254. // if the link connects to this node, highlight it
  255. function linksTo(x, i) {
  256. if (x instanceof go.Node) {
  257. x.findLinksInto().each(function (link) {
  258. link.highlight = i;
  259. });
  260. }
  261. }
  262. // if the link comes from this node, highlight it
  263. function linksFrom(x, i) {
  264. if (x instanceof go.Node) {
  265. x.findLinksOutOf().each(function (link) {
  266. link.highlight = i;
  267. });
  268. }
  269. }
  270. // highlight all links connected to this node
  271. function linksAll(x, i) {
  272. if (x instanceof go.Node) {
  273. x.linksConnected.each(function (link) {
  274. link.highlight = i;
  275. });
  276. }
  277. }
  278. // If selected object is a link, highlight its fromNode.
  279. // Otherwise highlight the fromNode of each link coming into the selected node.
  280. // Return a List of the keys of the nodes.
  281. function nodesTo(x, i) {
  282. var nodesToList = new go.List(/*"string"*/);
  283. if (x instanceof go.Link) {
  284. x.fromNode.highlight = i;
  285. nodesToList.add(x.data.from);
  286. } else {
  287. x.findNodesInto().each(function (node) {
  288. node.highlight = i;
  289. nodesToList.add(node.data.key);
  290. });
  291. }
  292. return nodesToList;
  293. }
  294. // same as nodesTo, but 'from' instead of 'to'
  295. function nodesFrom(x, i) {
  296. var nodesFromList = new go.List(/*"string"*/);
  297. if (x instanceof go.Link) {
  298. x.toNode.highlight = i;
  299. nodesFromList.add(x.data.to);
  300. } else {
  301. x.findNodesOutOf().each(function (node) {
  302. node.highlight = i;
  303. nodesFromList.add(node.data.key);
  304. });
  305. }
  306. return nodesFromList;
  307. }
  308. // If x is a link, highlight its toNode, or if it is a node, the node(s) it links to,
  309. // and then call nodesReach on the highlighted node(s), with the next color.
  310. // Do not highlight any node that has already been highlit with a color
  311. // indicating a closer relationship to the original node.
  312. function nodesReach(x, i) {
  313. if (x instanceof go.Link) {
  314. x.toNode.highlight = i;
  315. nodesReach(x.toNode, i + 1);
  316. } else {
  317. x.findNodesOutOf().each(function (node) {
  318. if (node.highlight === 0 || node.highlight > i) {
  319. node.highlight = i;
  320. nodesReach(node, i + 1);
  321. }
  322. });
  323. }
  324. }
  325. // highlight all nodes linked to this one
  326. function nodesConnect(x, i) {
  327. if (x instanceof go.Link) {
  328. x.toNode.highlight = i;
  329. x.fromNode.highlight = i;
  330. } else {
  331. x.findNodesConnected().each(function (node) {
  332. node.highlight = i;
  333. });
  334. }
  335. }
  336. // highlights the group containing this object, specific method for links
  337. // returns the containing group of x
  338. function containing(x, i) {
  339. var container = x.containingGroup;
  340. if (container !== null)
  341. container.highlight = i;
  342. return container;
  343. }
  344. // container is the group that contains this node and
  345. // will be the parameter x for the next call of this function.
  346. // Calling containing(x,i) highlights each group the appropriate color
  347. function containingAll(x, i) {
  348. containing(x, i);
  349. var container = x.containingGroup;
  350. if (container !== null)
  351. containingAll(container, i + 1);
  352. }
  353. // if the Node"s containingGroup is x, highlight it
  354. function childNodes(x, i) {
  355. var childLst = new go.List(/*"string"*/);
  356. if (x instanceof go.Group) {
  357. myDiagram.nodes.each(function (node) {
  358. if (node.containingGroup === x) {
  359. node.highlight = i;
  360. childLst.add(node.data.key);
  361. }
  362. });
  363. }
  364. return childLst;
  365. }
  366. // same as childNodes, then run allMemberNodes for each child Group with the next color
  367. function allMemberNodes(x, i) {
  368. if (x instanceof go.Group) {
  369. myDiagram.nodes.each(function (node) {
  370. if (node.containingGroup === x) {
  371. node.highlight = i;
  372. allMemberNodes(node, i + 1);
  373. }
  374. });
  375. }
  376. }
  377. // if the link"s containing Group is x, highlight it
  378. function childLinks(x, i) {
  379. var childLst = new go.List(/*go.Link*/);
  380. myDiagram.links.each(function (link) {
  381. if (link.containingGroup === x) {
  382. link.highlight = i;
  383. childLst.add(link);
  384. }
  385. });
  386. return childLst;
  387. }
  388. // same as childLinks, then run allMemberLinks for each child Group with the next color
  389. function allMemberLinks(x, i) {
  390. childLinks(x, i);
  391. myDiagram.nodes.each(function (node) {
  392. if (node instanceof go.Group && node.containingGroup === x) {
  393. allMemberLinks(node, i + 1);
  394. }
  395. });
  396. }
  397. // perform the actual highlighting
  398. function highlight(shp, obj2, hl) {
  399. var color;
  400. var width = 3;
  401. if (hl === 0) {
  402. color = "black";
  403. width = 1;
  404. } else if (hl === 1) {
  405. color = "blue";
  406. } else if (hl === 2) {
  407. color = "green";
  408. } else if (hl === 3) {
  409. color = "orange";
  410. } else if (hl === 4) {
  411. color = "red";
  412. } else {
  413. color = "purple";
  414. }
  415. shp.stroke = color;
  416. shp.strokeWidth = width;
  417. if (obj2 !== null) {
  418. obj2.stroke = color;
  419. obj2.fill = color;
  420. }
  421. }
  422. // return the selected radio button in "highlight"
  423. function getRadioButton() {
  424. var radio = document.getElementsByName("highlight");
  425. for (var i = 0; i < radio.length; i++)
  426. if (radio[i].checked)
  427. return radio[i];
  428. }
  429. // returns the text for a tooltip, param obj is the text itself
  430. function getInfo(model, obj) {
  431. var x = obj.panel.adornedPart; // the object that the mouse is over
  432. var text = ""; // what will be displayed
  433. if (x instanceof go.Node) {
  434. if (x instanceof go.Group)
  435. text += "Group: ";
  436. else
  437. text += "Node: ";
  438. text += x.data.key;
  439. var toLst = nodesTo(x, 0); // display names of nodes going into this node
  440. if (toLst.count > 0) {
  441. toLst.sort(function (a, b) {
  442. return a < b ? -1 : 1
  443. });
  444. text += "\nNodes into: ";
  445. toLst.each(function (key) {
  446. if (key !== text.substring(text.length - 3, text.length - 2)) {
  447. text += key + ", ";
  448. }
  449. });
  450. text = text.substring(0, text.length - 2);
  451. }
  452. var frLst = nodesFrom(x, 0); // display names of nodes coming out of this node
  453. if (frLst.count > 0) {
  454. frLst.sort(function (a, b) {
  455. return a < b ? -1 : 1
  456. });
  457. text += "\nNodes out of: ";
  458. frLst.each(function (key) {
  459. if (key !== text.substring(text.length - 3, text.length - 2)) {
  460. text += key + ", ";
  461. }
  462. });
  463. text = text.substring(0, text.length - 2);
  464. }
  465. var grpC = containing(x, 0); // if the node is in a group, display its name
  466. if (grpC !== null)
  467. text += "\nContaining SubGraph: " + grpC.data.key;
  468. if (x instanceof go.Group) {
  469. // if it"s a group, also display nodes and links contained in it
  470. text += "\nMember nodes: ";
  471. var children = childNodes(x, 0);
  472. children.sort(function (a, b) {
  473. return a < b ? -1 : 1
  474. });
  475. children.each(function (key) {
  476. if (key !== text.substring(text.length - 3, text.length - 2)) {
  477. text += key + ", ";
  478. }
  479. });
  480. text = text.substring(0, text.length - 2);
  481. var linkChildren = childLinks(x, 0);
  482. if (linkChildren.count > 0) {
  483. text += "\nMember links: ";
  484. var linkStrings = new go.List(/*"string"*/);
  485. linkChildren.each(function (link) {
  486. linkStrings.add(link.data.from + " --> " + link.data.to);
  487. });
  488. linkStrings.sort(function (a, b) {
  489. return a < b ? -1 : 1
  490. });
  491. linkStrings.each(function (str) {
  492. text += str + ", ";
  493. });
  494. text = text.substring(0, text.length - 2);
  495. }
  496. }
  497. } else if (x instanceof go.Link) {
  498. // if it"s a link, display its to and from nodes
  499. text += "Link: " + x.data.from + " --> " + x.data.to +
  500. "\nNode To: " + x.data.to + "\nNode From: " + x.data.from;
  501. var grp = containing(x, 0); // and containing group, if it has one
  502. if (grp !== null)
  503. text += "\nContaining SubGraph: " + grp.data.key;
  504. }
  505. return text;
  506. }
  507. window.addEventListener('DOMContentLoaded', initGo);