1. var $ = go.GraphObject.make; // for conciseness in defining templates
  2. function buildAlarm(row,column,columnSpan=1){
  3. var obj=$(go.Shape, "Rectangle", // define the node's outer shape
  4. {fill: "yellow", stroke: "black",alignment: go.Spot.TopRight,row: row, column: column, margin: 2, },
  5. new go.Binding("fill", "color"),
  6. new go.Binding("desiredSize", "", function(){ return new go.Size(40, 20) }));
  7. return obj;
  8. }
  9. function buildNodeName(row,column,columnSpan=1){
  10. var obj=$(go.TextBlock,
  11. {
  12. row: row, column: column,columnSpan:columnSpan,
  13. maxSize: new go.Size(160, NaN), margin: 2,
  14. font: '500 16px Roboto, sans-serif',
  15. alignment: go.Spot.Top,
  16. editable: true,
  17. isMultiline: false,
  18. minSize: new go.Size(10, 16)
  19. },
  20. new go.Binding("text", "name")
  21. );
  22. return obj;
  23. }
  24. function buildFields(row,column,columnSpan=1){
  25. var obj=$(go.TextBlock,
  26. {
  27. row: row, column: column, columnSpan: columnSpan,
  28. font: "12px Roboto, sans-serif",
  29. editable: true,
  30. isMultiline: true,
  31. name: "LIST",
  32. //minSize: new go.Size(10, 16),
  33. },
  34. new go.Binding("text", "", theInfoTextConverter));
  35. return obj;
  36. }
  37. function buildExpandNode(){
  38. var obj=$(go.Panel, // this is underneath the "BODY"
  39. { height: 15 }, // always this height, even if the TreeExpanderButton is not visible
  40. $("TreeExpanderButton"));
  41. return obj;
  42. }
  43. function buildContentTable(){
  44. var obj=$(go.Panel, "Table",
  45. { margin: 6,
  46. maxSize: new go.Size(250, NaN),
  47. margin: new go.Margin(6, 10, 0, 3),
  48. defaultAlignment: go.Spot.Left
  49. },
  50. // the two TextBlocks in column 0 both stretch in width
  51. // but align on the left side
  52. $(go.RowColumnDefinition,
  53. {
  54. column: 0,
  55. // width: 80 ,
  56. stretch: go.GraphObject.Horizontal,
  57. alignment: go.Spot.Left
  58. }),
  59. // the name
  60. //标题
  61. buildNodeName(0,0),
  62. //报警标识
  63. buildAlarm(0,1),
  64. $("PanelExpanderButton", "LIST", // the name of the element whose visibility this button toggles
  65. { row: 1, column: 2,columnSpan:1, alignment: go.Spot.Center, margin: 0, }),
  66. //属性字段
  67. buildFields(2,0,2));
  68. return obj;
  69. }
  70. function buildBackground(){
  71. var obj=$(go.Shape, "Rectangle",
  72. { stroke: null, strokeWidth: 0 },
  73. new go.Binding("fill", "isHighlighted", function(h) { return h ? "#F44336" : "#A7E7FC"; }).ofObject());
  74. return obj;
  75. }
  76. var nodeTemplateFactory={
  77. buildDefaultNodeTemplate:function(){
  78. var obj=$(go.Node, "Vertical",
  79. { selectionObjectName: "BODY", deletable: false,
  80. //desiredSize: new go.Size(300, 200),
  81. doubleClick: nodeDoubleClick,
  82. mouseEnter: mouseEnter,
  83. mouseLeave: mouseLeave,
  84. selectionChanged:nodeSelectionChanged,
  85. isShadowed: true,
  86. shadowColor: "#C5C1AA",
  87. //resizable: true,
  88. toolTip:
  89. $(go.Adornment, "Auto",
  90. $(go.Shape, { fill: "lightyellow" }),
  91. $(go.TextBlock, "double-click\nfor documentation",
  92. { margin: 5 })
  93. ),
  94. },
  95. $(go.Panel,"Auto",
  96. { name: "BODY" },
  97. // the outer shape for the node, surrounding the Table
  98. buildBackground(),
  99. // a table to contain the different parts of the node
  100. buildContentTable()),
  101. buildExpandNode());
  102. return obj;
  103. },
  104. buildEnvNodeTemplate:function(){
  105. }
  106. }
  107. var nodeIdCounter = -1; // use a sequence to guarantee key uniqueness as we add/remove/modify nodes
  108. var myDiagram =
  109. $(go.Diagram, "myDiagramDiv", // the DIV HTML element
  110. {
  111. // Put the diagram contents at the top center of the viewport
  112. initialDocumentSpot: go.Spot.TopCenter,
  113. initialViewportSpot: go.Spot.TopCenter,
  114. initialAutoScale: go.Diagram.UniformToFill,
  115. maxSelectionCount: 1,
  116. //initialAutoScale: go.Diagram.Uniform,
  117. validCycle: go.Diagram.CycleDestinationTree, // make sure users can only create trees
  118. "clickCreatingTool.archetypeNodeData": {}, // allow double-click in background to create a new node
  119. "clickCreatingTool.insertPart": function(loc) { // customize the data for the new node
  120. this.archetypeNodeData = {
  121. key: getNextKey(), // assign the key based on the number of nodes
  122. name: "(new person)",
  123. title: ""
  124. };
  125. return go.ClickCreatingTool.prototype.insertPart.call(this, loc);
  126. },
  127. // allow double-click in background to create a new node
  128. "clickCreatingTool.archetypeNodeData": { text: "Node", color: "white" },
  129. // allow Ctrl-G to call groupSelection()
  130. "commandHandler.archetypeGroupData": { text: "Group", isGroup: true, color: "blue" },
  131. // OR: Scroll to show a particular node, once the layout has determined where that node is
  132. //"InitialLayoutCompleted": function(e) {
  133. // var node = e.diagram.findNodeForKey(28);
  134. // if (node !== null) e.diagram.commandHandler.scrollToPart(node);
  135. //},
  136. layout:
  137. $(go.TreeLayout, // use a TreeLayout to position all of the nodes
  138. {
  139. //treeStyle: go.TreeLayout.StyleLastParents,
  140. // properties for most of the tree:
  141. angle: 90,
  142. nodeSpacing: 10,
  143. layerSpacing: 60,
  144. arrangement: go.TreeLayout.ArrangementHorizontal,
  145. // properties for the "last parents":
  146. alternateAngle: 0,
  147. alternateAlignment: go.TreeLayout.AlignmentStart,
  148. alternateNodeIndent: 20,
  149. alternateNodeIndentPastParent: 1,
  150. alternateNodeSpacing: 20,
  151. alternateLayerSpacing: 40,
  152. alternateLayerSpacingParentOverlap: 1,
  153. alternatePortSpot: new go.Spot(0.001, 1, 20, 0),
  154. alternateChildPortSpot: go.Spot.Left
  155. }),
  156. "undoManager.isEnabled": true // enable undo & redo
  157. });
  158. myDiagram.nodeTemplate =nodeTemplateFactory.buildDefaultNodeTemplate();
  159. myDiagram.linkTemplate =$(go.Link, go.Link.Orthogonal,
  160. { corner: 5, selectable: false },
  161. $(go.Shape, { strokeWidth: 3, stroke: "#424242" } ));
  162. /*
  163. myDiagram.linkTemplate =
  164. $(go.Link,
  165. {
  166. curve: go.Link.Bezier,
  167. toEndSegmentLength: 30, fromEndSegmentLength: 30
  168. },
  169. $(go.Shape, { strokeWidth: 1.5 }) // the link shape, with the default black stroke
  170. );
  171. */
  172. // Overview
  173. var myOverview =
  174. $(go.Overview, "myOverviewDiv", // the HTML DIV element for the Overview
  175. { observed: myDiagram, contentAlignment: go.Spot.Center }); // tell it which Diagram to show and pan
  176. // define Converters to be used for Bindings
  177. myDiagram.addDiagramListener("Modified", function(e) {
  178. var button = document.getElementById("SaveButton");
  179. if (button) button.disabled = !myDiagram.isModified;
  180. var idx = document.title.indexOf("*");
  181. if (myDiagram.isModified) {
  182. if (idx < 0) document.title += "*";
  183. } else {
  184. if (idx >= 0) document.title = document.title.substr(0, idx);
  185. }
  186. });
  187. myDiagram.addDiagramListener("SelectionDeleting", function(e) {
  188. var part = e.subject.first(); // e.subject is the myDiagram.selection collection,
  189. // so we'll get the first since we know we only have one selection
  190. myDiagram.startTransaction("clear boss");
  191. if (part instanceof go.Node) {
  192. var it = part.findTreeChildrenNodes(); // find all child nodes
  193. while(it.next()) { // now iterate through them and clear out the boss information
  194. var child = it.value;
  195. var bossText = child.findObject("boss"); // since the boss TextBlock is named, we can access it by name
  196. if (bossText === null) return;
  197. bossText.text = undefined;
  198. }
  199. } else if (part instanceof go.Link) {
  200. var child = part.toNode;
  201. var bossText = child.findObject("boss"); // since the boss TextBlock is named, we can access it by name
  202. if (bossText === null) return;
  203. bossText.text = undefined;
  204. }
  205. myDiagram.commitTransaction("clear boss");
  206. });
  207. var levelColors = ["#AC193D/#BF1E4B", "#2672EC/#2E8DEF", "#8C0095/#A700AE", "#5133AB/#643EBF",
  208. "#008299/#00A0B1", "#D24726/#DC572E", "#008A00/#00A600", "#094AB2/#0A5BC4"];
  209. // override TreeLayout.commitNodes to also modify the background brush based on the tree depth level
  210. myDiagram.layout.commitNodes = function() {
  211. go.TreeLayout.prototype.commitNodes.call(myDiagram.layout); // do the standard behavior
  212. // then go through all of the vertexes and set their corresponding node's Shape.fill
  213. // to a brush dependent on the TreeVertex.level value
  214. myDiagram.layout.network.vertexes.each(function(v) {
  215. if (v.node) {
  216. var level = v.level % (levelColors.length);
  217. var colors = levelColors[level].split("/");
  218. var shape = v.node.findObject("SHAPE");
  219. if (shape) shape.fill = $(go.Brush, "Linear", { 0: colors[0], 1: colors[1], start: go.Spot.Left, end: go.Spot.Right });
  220. }
  221. });
  222. };
  223. // This function is used to find a suitable ID when modifying/creating nodes.
  224. // We used the counter combined with findNodeDataForKey to ensure uniqueness.
  225. function getNextKey() {
  226. var key = nodeIdCounter;
  227. while (myDiagram.model.findNodeDataForKey(key.toString()) !== null) {
  228. key = nodeIdCounter -= 1;
  229. }
  230. return key.toString();
  231. }
  232. function nodeDoubleClick(e, obj) {
  233. var clicked = obj.part;
  234. if (clicked !== null) {
  235. var thisemp = clicked.data;
  236. myDiagram.startTransaction("add employee");
  237. var nextkey = getNextKey();
  238. var newemp = { key: nextkey, name: "(new person)", title: "", parent: thisemp.key };
  239. myDiagram.model.addNodeData(newemp);
  240. myDiagram.commitTransaction("add employee");
  241. }
  242. }
  243. function theNationFlagConverter(nation) {
  244. return "https://www.nwoods.com/go/Flags/" + nation.toLowerCase().replace(/\s/g, "-") + "-flag.Png";
  245. }
  246. function theInfoTextConverter(info) {
  247. var str = "";
  248. if (info.title) str += "Title: " + info.title;
  249. if (info.headOf) str += "\n\nHead of: " + info.headOf;
  250. if (typeof info.boss === "number") {
  251. var bossinfo = myDiagram.model.findNodeDataForKey(info.boss);
  252. if (bossinfo !== null) {
  253. str += "\n\nReporting to: " + bossinfo.name;
  254. }
  255. }
  256. return str;
  257. }
  258. // set up the nodeDataArray, describing each person/position
  259. var nodeDataArray = [
  260. { key: 0, name: "Ban Ki-moon 반기문", nation: "South Korea", title: "Secretary-General of the United Nations", headOf: "Secretariat" },
  261. { key: 1, boss: 0, name: "Patricia O'Brien", nation: "Ireland", title: "Under-Secretary-General for Legal Affairs and United Nations Legal Counsel", headOf: "Office of Legal Affairs" },
  262. { key: 3, boss: 1, name: "Peter Taksøe-Jensen", nation: "Denmark", title: "Assistant Secretary-General for Legal Affairs" },
  263. { key: 9, boss: 3, name: "Other Employees" },
  264. { key: 4, boss: 1, name: "Maria R. Vicien - Milburn", nation: "Argentina", title: "General Legal Division Director", headOf: "General Legal Division" },
  265. { key: 10, boss: 4, name: "Other Employees" },
  266. { key: 5, boss: 1, name: "Václav Mikulka", nation: "Czech Republic", title: "Codification Division Director", headOf: "Codification Division" },
  267. { key: 11, boss: 5, name: "Other Employees" },
  268. { key: 6, boss: 1, name: "Sergei Tarassenko", nation: "Russia", title: "Division for Ocean Affairs and the Law of the Sea Director", headOf: "Division for Ocean Affairs and the Law of the Sea" },
  269. { key: 12, boss: 6, name: "Alexandre Tagore Medeiros de Albuquerque", nation: "Brazil", title: "Chairman of the Commission on the Limits of the Continental Shelf", headOf: "The Commission on the Limits of the Continental Shelf" },
  270. { key: 17, boss: 12, name: "Peter F. Croker", nation: "Ireland", title: "Chairman of the Committee on Confidentiality", headOf: "The Committee on Confidentiality" },
  271. { key: 31, boss: 17, name: "Michael Anselme Marc Rosette", nation: "Seychelles", title: "Vice Chairman of the Committee on Confidentiality" },
  272. { key: 32, boss: 17, name: "Kensaku Tamaki", nation: "Japan", title: "Vice Chairman of the Committee on Confidentiality" },
  273. { key: 33, boss: 17, name: "Osvaldo Pedro Astiz", nation: "Argentina", title: "Member of the Committee on Confidentiality" },
  274. { key: 34, boss: 17, name: "Yuri Borisovitch Kazmin", nation: "Russia", title: "Member of the Committee on Confidentiality" },
  275. { key: 18, boss: 12, name: "Philip Alexander Symonds", nation: "Australia", title: "Chairman of the Committee on provision of scientific and technical advice to coastal States", headOf: "Committee on provision of scientific and technical advice to coastal States"},
  276. { key: 35, boss: 18, name: "Emmanuel Kalngui", nation: "Cameroon", title: "Vice Chairman of the Committee on provision of scientific and technical advice to coastal States" },
  277. { key: 36, boss: 18, name: "Sivaramakrishnan Rajan", nation: "India", title: "Vice Chairman of the Committee on provision of scientific and technical advice to coastal States" },
  278. { key: 37, boss: 18, name: "Francis L. Charles", nation: "Trinidad and Tobago", title: "Member of the Committee on provision of scientific and technical advice to costal States"},
  279. { key: 38, boss: 18, name: "Mihai Silviu German", nation: "Romania", title: "Member of the Committee on provision of scientific and technical advice to costal States"},
  280. { key: 19, boss: 12, name: "Lawrence Folajimi Awosika", nation: "Nigeria", title: "Vice Chairman of the Commission on the Limits of the Continental Shelf" },
  281. { key: 20, boss: 12, name: "Harald Brekke", nation: "Norway", title: "Vice Chairman of the Commission on the Limits of the Continental Shelf" },
  282. { key: 21, boss: 12, name: "Yong-Ahn Park", nation: "South Korea", title: "Vice Chairman of the Commission on the Limits of the Continental Shelf" },
  283. { key: 22, boss: 12, name: "Abu Bakar Jaafar", nation: "Malaysia", title: "Chairman of the Editorial Committee", headOf: "Editorial Committee" },
  284. { key: 23, boss: 12, name: "Galo Carrera Hurtado", nation: "Mexico", title: "Chairman of the Training Committee", headOf: "Training Committee" },
  285. { key: 24, boss: 12, name: "Indurlall Fagoonee", nation: "Mauritius", title: "Member of the Commission on the Limits of the Continental Shelf" },
  286. { key: 25, boss: 12, name: "George Jaoshvili", nation: "Georgia", title: "Member of the Commission on the Limits of the Continental Shelf" },
  287. { key: 26, boss: 12, name: "Wenzhang Lu", nation: "China", title: "Member of the Commission on the Limits of the Continental Shelf" },
  288. { key: 27, boss: 12, name: "Isaac Owusu Orudo", nation: "Ghana", title: "Member of the Commission on the Limits of the Continental Shelf" },
  289. { key: 28, boss: 12, name: "Fernando Manuel Maia Pimentel", nation: "Portugal", title: "Member of the Commission on the Limits of the Continental Shelf" },
  290. { key: 7, boss: 1, name: "Renaud Sorieul", nation: "France", title: "International Trade Law Division Director", headOf: "International Trade Law Division" },
  291. { key: 13, boss: 7, name: "Other Employees" },
  292. { key: 8, boss: 1, name: "Annebeth Rosenboom", nation: "Netherlands", title: "Treaty Section Chief", headOf: "Treaty Section" },
  293. { key: 14, boss: 8, name: "Bradford Smith", nation: "United States", title: "Substantive Legal Issues Head", headOf: "Substantive Legal Issues" },
  294. { key: 29, boss: 14, name: "Other Employees" },
  295. { key: 15, boss: 8, name: "Andrei Kolomoets", nation: "Russia", title: "Technical/Legal Issues Head", headOf: "Technical/Legal Issues" },
  296. { key: 30, boss: 15, name: "Other Employees" },
  297. { key: 16, boss: 8, name: "Other Employees" },
  298. { key: 2, boss: 0, name: "Heads of Other Offices/Departments" }
  299. ];
  300. // the Search functionality highlights all of the nodes that have at least one data property match a RegExp
  301. function searchDiagram() { // called by button
  302. var input = document.getElementById("mySearch");
  303. if (!input) return;
  304. input.focus();
  305. // create a case insensitive RegExp from what the user typed
  306. var regex = new RegExp(input.value, "i");
  307. myDiagram.startTransaction("highlight search");
  308. myDiagram.clearHighlighteds();
  309. // search four different data properties for the string, any of which may match for success
  310. if (input.value) { // empty string only clears highlighteds collection
  311. var results = myDiagram.findNodesByExample({ name: regex },
  312. { nation: regex },
  313. { title: regex },
  314. { headOf: regex });
  315. myDiagram.highlightCollection(results);
  316. // try to center the diagram at the first node that was found
  317. if (results.count > 0) myDiagram.centerRect(results.first().actualBounds);
  318. }
  319. myDiagram.commitTransaction("highlight search");
  320. }
  321. // this event handler is called when the diagram is first ready
  322. myDiagram.addDiagramListener("InitialLayoutCompleted", function(e) {
  323. // pick a random node data
  324. //var data = nodeDataArray[Math.floor(Math.random()*nodeDataArray.length)];
  325. var data=nodeDataArray[0];
  326. // find the corresponding Node
  327. var node = myDiagram.findNodeForData(data);
  328. // and center it and select it
  329. myDiagram.centerRect(node.actualBounds);
  330. myDiagram.select(node);
  331. });
  332. //修改节点时触发
  333. myDiagram.addModelChangedListener(function(evt) {
  334. // ignore unimportant Transaction events
  335. if (!evt.isTransactionFinished) return;
  336. var txn = evt.object; // a Transaction
  337. if (txn === null) return;
  338. // iterate over all of the actual ChangedEvents of the Transaction
  339. txn.changes.each(function(e) {
  340. // ignore any kind of change other than adding/removing a node
  341. if (e.modelChange !== "nodeDataArray") return;
  342. // record node insertions and removals
  343. if (e.change === go.ChangedEvent.Insert) {
  344. console.log(evt.propertyName + " added node with key: " + e.newValue.key);
  345. } else if (e.change === go.ChangedEvent.Remove) {
  346. console.log(evt.propertyName + " removed node with key: " + e.oldValue.key);
  347. }
  348. });
  349. });
  350. //连接改变时触发
  351. myDiagram.addModelChangedListener(function(evt) {
  352. // ignore unimportant Transaction events
  353. if (!evt.isTransactionFinished) return;
  354. var txn = evt.object; // a Transaction
  355. if (txn === null) return;
  356. // iterate over all of the actual ChangedEvents of the Transaction
  357. txn.changes.each(function(e) {
  358. // record node insertions and removals
  359. if (e.change === go.ChangedEvent.Property) {
  360. if (e.modelChange === "linkFromKey") {
  361. console.log(evt.propertyName + " changed From key of link: " +
  362. e.object + " from: " + e.oldValue + " to: " + e.newValue);
  363. } else if (e.modelChange === "linkToKey") {
  364. console.log(evt.propertyName + " changed To key of link: " +
  365. e.object + " from: " + e.oldValue + " to: " + e.newValue);
  366. }
  367. } else if (e.change === go.ChangedEvent.Insert && e.modelChange === "linkDataArray") {
  368. console.log(evt.propertyName + " added link: " + e.newValue);
  369. } else if (e.change === go.ChangedEvent.Remove && e.modelChange === "linkDataArray") {
  370. console.log(evt.propertyName + " removed link: " + e.oldValue);
  371. }
  372. });
  373. });
  374. // To simplify this code we define a function for creating a context menu button:
  375. function makeButton(text, action, visiblePredicate) {
  376. return $("ContextMenuButton",
  377. $(go.TextBlock, text),
  378. { click: action },
  379. // don't bother with binding GraphObject.visible if there's no predicate
  380. visiblePredicate ? new go.Binding("visible", "", visiblePredicate).ofObject() : {});
  381. }
  382. var partContextMenu =
  383. $(go.Adornment, "Vertical",
  384. makeButton("Properties",
  385. function(e, obj) { // OBJ is this Button
  386. var contextmenu = obj.part; // the Button is in the context menu Adornment
  387. var part = contextmenu.adornedPart; // the adornedPart is the Part that the context menu adorns
  388. // now can do something with PART, or with its data, or with the Adornment (the context menu)
  389. if (part instanceof go.Link) alert(linkInfo(part.data));
  390. else if (part instanceof go.Group) alert(groupInfo(contextmenu));
  391. else alert(nodeInfo(part.data));
  392. }),
  393. makeButton("Cut",
  394. function(e, obj) { e.diagram.commandHandler.cutSelection(); },
  395. function(o) { return o.diagram.commandHandler.canCutSelection(); }),
  396. makeButton("Copy",
  397. function(e, obj) { e.diagram.commandHandler.copySelection(); },
  398. function(o) { return o.diagram.commandHandler.canCopySelection(); }),
  399. makeButton("Paste",
  400. function(e, obj) { e.diagram.commandHandler.pasteSelection(e.diagram.lastInput.documentPoint); },
  401. function(o) { return o.diagram.commandHandler.canPasteSelection(); }),
  402. makeButton("Delete",
  403. function(e, obj) { e.diagram.commandHandler.deleteSelection(); },
  404. function(o) { return o.diagram.commandHandler.canDeleteSelection(); }),
  405. makeButton("Undo",
  406. function(e, obj) { e.diagram.commandHandler.undo(); },
  407. function(o) { return o.diagram.commandHandler.canUndo(); }),
  408. makeButton("Redo",
  409. function(e, obj) { e.diagram.commandHandler.redo(); },
  410. function(o) { return o.diagram.commandHandler.canRedo(); }),
  411. makeButton("Group",
  412. function(e, obj) { e.diagram.commandHandler.groupSelection(); },
  413. function(o) { return o.diagram.commandHandler.canGroupSelection(); }),
  414. makeButton("Ungroup",
  415. function(e, obj) { e.diagram.commandHandler.ungroupSelection(); },
  416. function(o) { return o.diagram.commandHandler.canUngroupSelection(); })
  417. );
  418. function nodeInfo(d) { // Tooltip info for a node data object
  419. var str = "Node " + d.key + ": " + d.text + "\n";
  420. if (d.group)
  421. str += "member of " + d.group;
  422. else
  423. str += "top-level node";
  424. return str;
  425. }
  426. // When a Node is selected, highlight the corresponding HTML element.
  427. function nodeSelectionChanged(node) {
  428. if (node.isSelected) {
  429. //names[node.data.name].style.backgroundColor = "lightblue";
  430. // node.style.backgroundColor = "lightblue";
  431. console.log(node.data.name);
  432. } else {
  433. //names[node.data.name].style.backgroundColor = "";
  434. }
  435. }
  436. function mouseEnter(e, obj) {
  437. obj.isHighlighted = true;
  438. };
  439. function mouseLeave(e, obj) {
  440. obj.isHighlighted = false;
  441. };
  442. //linkData在父亲节点都不存在的情况下会自动创建Node
  443. //{ from: "Center", to: i++, toArrow: arrowheads[j], fromArrow: arrowheads[j + 1] }
  444. // a selected node shows an Adornment that includes both a blue border
  445. // and a row of Buttons above the node
  446. myDiagram.nodeTemplate.selectionAdornmentTemplate =
  447. $(go.Adornment, "Spot",
  448. $(go.Panel, "Auto",
  449. $(go.Shape, { stroke: "dodgerblue", strokeWidth: 2, fill: null }),
  450. $(go.Placeholder)
  451. ),
  452. $(go.Panel, "Horizontal",
  453. { alignment: go.Spot.Top, alignmentFocus: go.Spot.Bottom },
  454. $("Button",
  455. { click: editText }, // defined below, to support editing the text of the node
  456. $(go.TextBlock, "t",
  457. { font: "bold 10pt sans-serif", desiredSize: new go.Size(15, 15), textAlign: "center" })
  458. ),
  459. $("Button",
  460. { click: changeColor, "_buttonFillOver": "transparent" }, // defined below, to support changing the color of the node
  461. new go.Binding("ButtonBorder.fill", "color", nextColor),
  462. $(go.Shape,
  463. { fill: null, stroke: null, desiredSize: new go.Size(14, 14) })
  464. ),
  465. $("Button",
  466. { // drawLink is defined below, to support interactively drawing new links
  467. click: drawLink, // click on Button and then click on target node
  468. actionMove: drawLink // drag from Button to the target node
  469. },
  470. $(go.Shape,
  471. { geometryString: "M0 0 L8 0 8 12 14 12 M12 10 L14 12 12 14" })
  472. ),
  473. $("Button",
  474. {
  475. actionMove: dragNewNode, // defined below, to support dragging from the button
  476. _dragData: { text: "a Node", color: "lightgray" }, // node data to copy
  477. click: clickNewNode // defined below, to support a click on the button
  478. },
  479. $(go.Shape,
  480. { geometryString: "M0 0 L3 0 3 10 6 10 x F1 M6 6 L14 6 14 14 6 14z", fill: "gray" })
  481. )
  482. )
  483. );
  484. function editText(e, button) {
  485. var node = button.part.adornedPart;
  486. e.diagram.commandHandler.editTextBlock(node.findObject("TEXTBLOCK"));
  487. }
  488. function editText(e, button) {
  489. var node = button.part.adornedPart;
  490. e.diagram.commandHandler.editTextBlock(node.findObject("TEXTBLOCK"));
  491. }
  492. // used by nextColor as the list of colors through which we rotate
  493. var myColors = ["lightgray", "lightblue", "lightgreen", "yellow", "orange", "pink"];
  494. // used by both the Button Binding and by the changeColor click function
  495. function nextColor(c) {
  496. var idx = myColors.indexOf(c);
  497. if (idx < 0) return "lightgray";
  498. if (idx >= myColors.length-1) idx = 0;
  499. return myColors[idx+1];
  500. }
  501. function changeColor(e, button) {
  502. var node = button.part.adornedPart;
  503. var shape = node.findObject("SHAPE");
  504. if (shape === null) return;
  505. node.diagram.startTransaction("Change color");
  506. shape.fill = nextColor(shape.fill);
  507. button["_buttonFillNormal"] = nextColor(shape.fill); // update the button too
  508. node.diagram.commitTransaction("Change color");
  509. }
  510. function drawLink(e, button) {
  511. var node = button.part.adornedPart;
  512. var tool = e.diagram.toolManager.linkingTool;
  513. tool.startObject = node.port;
  514. e.diagram.currentTool = tool;
  515. tool.doActivate();
  516. }
  517. // used by both clickNewNode and dragNewNode to create a node and a link
  518. // from a given node to the new node
  519. function createNodeAndLink(data, fromnode) {
  520. var diagram = fromnode.diagram;
  521. var model = diagram.model;
  522. var nodedata = model.copyNodeData(data);
  523. model.addNodeData(nodedata);
  524. var newnode = diagram.findNodeForData(nodedata);
  525. var linkdata = model.copyLinkData({});
  526. model.setFromKeyForLinkData(linkdata, model.getKeyForNodeData(fromnode.data));
  527. model.setToKeyForLinkData(linkdata, model.getKeyForNodeData(newnode.data));
  528. model.addLinkData(linkdata);
  529. diagram.select(newnode);
  530. return newnode;
  531. }
  532. // the Button.click event handler, called when the user clicks the "N" button
  533. function clickNewNode(e, button) {
  534. var data = button._dragData;
  535. if (!data) return;
  536. e.diagram.startTransaction("Create Node and Link");
  537. var fromnode = button.part.adornedPart;
  538. var newnode = createNodeAndLink(button._dragData, fromnode);
  539. newnode.location = new go.Point(fromnode.location.x + 200, fromnode.location.y);
  540. e.diagram.commitTransaction("Create Node and Link");
  541. }
  542. // the Button.actionMove event handler, called when the user drags within the "N" button
  543. function dragNewNode(e, button) {
  544. var tool = e.diagram.toolManager.draggingTool;
  545. if (tool.isBeyondDragSize()) {
  546. var data = button._dragData;
  547. if (!data) return;
  548. e.diagram.startTransaction("button drag"); // see doDeactivate, below
  549. var newnode = createNodeAndLink(data, button.part.adornedPart);
  550. newnode.location = e.diagram.lastInput.documentPoint;
  551. // don't commitTransaction here, but in tool.doDeactivate, after drag operation finished
  552. // set tool.currentPart to a selected movable Part and then activate the DraggingTool
  553. tool.currentPart = newnode;
  554. e.diagram.currentTool = tool;
  555. tool.doActivate();
  556. }
  557. }
  558. // using dragNewNode also requires modifying the standard DraggingTool so that it
  559. // only calls commitTransaction when dragNewNode started a "button drag" transaction;
  560. // do this by overriding DraggingTool.doDeactivate:
  561. var tool = myDiagram.toolManager.draggingTool;
  562. tool.doDeactivate = function() {
  563. // commit "button drag" transaction, if it is ongoing; see dragNewNode, above
  564. if (tool.diagram.undoManager.nestedTransactionNames.elt(0) === "button drag") {
  565. tool.diagram.commitTransaction();
  566. }
  567. go.DraggingTool.prototype.doDeactivate.call(tool); // call the base method
  568. };
  569. myDiagram.model =
  570. $(go.TreeModel,
  571. { nodeParentKeyProperty: "boss", // this property refers to the parent node data
  572. //nodeParentKeyProperty: "parentKey",
  573. nodeDataArray: nodeDataArray });
  574. //更新数据
  575. // model.updateTargetBindings(data);
  576. //循环更新数据
  577. /*
  578. function loop() {
  579. setTimeout(function() { randomProblems(); loop(); }, 2000);
  580. }
  581. loop(); // start the simulation
  582. */

【12-26】go.js的更多相关文章

  1. 【重温基础】15.JS对象介绍

    从这篇文章开始,复习 MDN 中级教程 的内容了,在初级教程中,我和大家分享了一些比较简单基础的知识点,并放在我的 [Cute-JavaScript]系列文章中. 关于[Cute-JavaScript ...

  2. 【开源专访】Sea.js创始人玉伯的前端开发之路

    摘要:玉伯,淘宝前端类库 KISSY.前端模块化开发框架SeaJS.前端基础类库Arale的创始人.本期[开源专访]我们邀请玉伯来为我们分享一些关于前端框架.前端开发的那些事,以及前端大牛是如何炼成的 ...

  3. 【23.26%】【codeforces 747D】Winter Is Coming

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  4. 【干货分享】Node.js 中文学习资料和教程导航

    这篇文章来自 Github 上的一位开发者收集整理的 Node.js 中文学习资料和教程导航.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念,它的目标是帮助程 ...

  5. 【Python + Selenium】之JS定位总结

    感谢:小琰子 Python+Selenium 脚本中的一些js的用法汇总: 1.滚动条 driver.set_window_size(500,500) js = "window.scroll ...

  6. 【干货分享】Node.js 中文资料导航

    这篇文章与大家分享一批高质量的的 Node.js 中文资料.Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台, 用来方便地搭建快速的, 易于扩展的网络应用 Node ...

  7. 【功能代码】---5 JS通过事件隐藏显示元素

    JS通过事件隐藏显示元素 在开发中,很多时候我们需要点击事件,才显示隐藏元素.那如何做到页面刚开始就把标签隐藏. 有两种方法: (1) display:none    <div id=" ...

  8. 【功能代码】---3 JS判断字符串是否包含某个字符串

    JS判断字符串是否包含某个字符串 var str ="abc"; if(str.indexOf("bc")>-1){ alert('str中包含bc字符串 ...

  9. 【12.78%】【codeforces 677D】Vanya and Treasure

    time limit per test1.5 seconds memory limit per test256 megabytes inputstandard input outputstandard ...

  10. 【特别推荐】Node.js 入门教程和学习资源汇总

    这篇文章与大家分享一批很有用的 Node.js 入门教程和学习资源.Node 是一个服务器端的 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...

随机推荐

  1. java中的SPI机制

    1 SPI机制简介 SPI的全名为Service Provider Interface.大多数开发人员可能不熟悉,因为这个是针对厂商或者插件的.在java.util.ServiceLoader的文档里 ...

  2. (转)Java中的static关键字解析

    转载: http://www.cnblogs.com/dolphin0520/p/3799052.html 一.static关键字的用途 在<Java编程思想>P86页有这样一段话: &q ...

  3. Ioc和Ao使用扩展

    一.Bean作用域 spring容器创建的时候,会将所有配置的bean对象创建出来,默认bean都是单例的.代码通过getBean()方法从容器获取指定的bean实例,容器首先会调用Bean类的无参构 ...

  4. BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]

    1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1367  Solved: 598[Submit][Status ...

  5. angular学习笔记(二十八)-$http(6)-使用ngResource模块构建RESTful架构

    ngResource模块是angular专门为RESTful架构而设计的一个模块,它提供了'$resource'模块,$resource模块是基于$http的一个封装.下面来看看它的详细用法 1.引入 ...

  6. VS 生成事件

    转载自: http://hi.baidu.com/gisince/item/7f0439ee610c94255a2d64b4 今天写了生成事件的处理,如下: 从网上Down了一个例子,运行时提示错误 ...

  7. 解读ASP.NET 5 & MVC6系列(16):自定义View视图文件查找逻辑

    之前MVC5和之前的版本中,我们要想对View文件的路径进行控制的话,则必须要对IViewEngine接口的FindPartialView或FindView方法进行重写,所有的视图引擎都继承于该IVi ...

  8. EF Code First 初体验

    Code First 顾名思义就是先代码,再由代码生成数据库的开发方式. 废话不多说,直接来一发看看:在VS2010里新建一个空白解决方案,再依次添加两个类库项目:Model.DataAccess和一 ...

  9. [LeetCode] First Bad Version 第一个坏版本

    You are a product manager and currently leading a team to develop a new product. Unfortunately, the ...

  10. [LeetCode] Trips and Users 旅行和用户

    The Trips table holds all taxi trips. Each trip has a unique Id, while Client_Id and Driver_Id are b ...