UNPKG

gojs

Version:

Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams

303 lines (282 loc) 15.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/> <meta name="description" content="When a diagram node is selected show a selection Adornment holding buttons on which a click invokes a command or a drag starts a tool"/> <link rel="stylesheet" href="../assets/css/style.css"/> <!-- Copyright 1998-2023 by Northwoods Software Corporation. --> <title>Selection Adornment Buttons</title> </head> <body> <!-- This top nav is not part of the sample code --> <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary"> <div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2"> <div class="md:pl-4"> <a class="text-white hover:text-white no-underline hover:no-underline font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../"> <h1 class="my-0 p-1 ">GoJS</h1> </a> </div> <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation"> <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6"> <path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path> <path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path> </svg> </button> <div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20"> <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0"> <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li> <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li> <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li> <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li> <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li> <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li> <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li> <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html" target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li> <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html" target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li> </ul> </div> </div> <hr class="border-b border-gray-600 opacity-50 my-0 py-0" /> </nav> <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto"> <div id="navSide" class="flex flex-col w-full md:w-48 text-gray-700 bg-white flex-shrink-0"></div> <!-- * * * * * * * * * * * * * --> <!-- Start of GoJS sample code --> <script src="../release/go.js"></script> <div id="allSampleContent" class="p-4 w-full"> <script id="code"> function init() { // As of 2.2, you can also author concise templates with method chaining // For details, see https://gojs.net/latest/intro/buildingObjects.html // Since 2.2 you can also author concise templates with method chaining instead of GraphObject.make // For details, see https://gojs.net/latest/intro/buildingObjects.html const $ = go.GraphObject.make; // for conciseness in defining templates myDiagram = new go.Diagram("myDiagramDiv", // create a Diagram for the DIV HTML element { "linkingTool.isEnabled": false, // invoked explicitly by drawLink function, below "linkingTool.direction": go.LinkingTool.ForwardsOnly, // only draw "from" towards "to" "undoManager.isEnabled": true // enable undo & redo }); myDiagram.linkTemplate = $(go.Link, { routing: go.Link.AvoidsNodes, corner: 5 }, $(go.Shape, { strokeWidth: 1.5 }), $(go.Shape, { toArrow: "OpenTriangle" }) ); myDiagram.nodeTemplate = $(go.Node, "Auto", { desiredSize: new go.Size(80, 80), // rearrange the link points evenly along the sides of the nodes as links are // drawn or reconnected -- these event handlers only make sense when the fromSpot // and toSpot are Spot.xxxSides linkConnected: (node, link, port) => { if (link.fromNode !== null) link.fromNode.invalidateConnectedLinks(); if (link.toNode !== null) link.toNode.invalidateConnectedLinks(); }, linkDisconnected: (node, link, port) => { if (link.fromNode !== null) link.fromNode.invalidateConnectedLinks(); if (link.toNode !== null) link.toNode.invalidateConnectedLinks(); }, locationSpot: go.Spot.Center }, new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify), $(go.Shape, { name: "SHAPE", // named so that changeColor can modify it strokeWidth: 0, // no border fill: "lightgray", // default fill color portId: "", // use the following property if you want users to draw new links // interactively by dragging from the Shape, and re-enable the LinkingTool // in the initialization of the Diagram //cursor: "pointer", fromSpot: go.Spot.AllSides, fromLinkable: true, fromLinkableDuplicates: true, fromLinkableSelfNode: true, toSpot: go.Spot.AllSides, toLinkable: true, toLinkableDuplicates: true, toLinkableSelfNode: true }, new go.Binding("fill", "color").makeTwoWay()), $(go.TextBlock, { name: "TEXTBLOCK", // named so that editText can start editing it margin: 3, // use the following property if you want users to interactively start // editing the text by clicking on it or by F2 if the node is selected: //editable: true, overflow: go.TextBlock.OverflowEllipsis, maxLines: 5 }, new go.Binding("text").makeTwoWay()) ); // a selected node shows an Adornment that includes both a blue border // and a row of Buttons above the node myDiagram.nodeTemplate.selectionAdornmentTemplate = $(go.Adornment, "Spot", $(go.Panel, "Auto", $(go.Shape, { stroke: "dodgerblue", strokeWidth: 2, fill: null }), $(go.Placeholder) ), $(go.Panel, "Horizontal", { alignment: go.Spot.Top, alignmentFocus: go.Spot.Bottom }, $("Button", { click: editText }, // defined below, to support editing the text of the node $(go.TextBlock, "t", { font: "bold 10pt sans-serif", desiredSize: new go.Size(15, 15), textAlign: "center" }) ), $("Button", { click: changeColor, "_buttonFillOver": "transparent" }, // defined below, to support changing the color of the node new go.Binding("ButtonBorder.fill", "color", nextColor), $(go.Shape, { fill: null, stroke: null, desiredSize: new go.Size(14, 14) }) ), $("Button", { // drawLink is defined below, to support interactively drawing new links click: drawLink, // click on Button and then click on target node actionMove: drawLink // drag from Button to the target node }, $(go.Shape, { geometryString: "M0 0 L8 0 8 12 14 12 M12 10 L14 12 12 14" }) ), $("Button", { actionMove: dragNewNode, // defined below, to support dragging from the button _dragData: { text: "a Node", color: "lightgray" }, // node data to copy click: clickNewNode // defined below, to support a click on the button }, $(go.Shape, { geometryString: "M0 0 L3 0 3 10 6 10 x F1 M6 6 L14 6 14 14 6 14z", fill: "gray" }) ) ) ); function editText(e, button) { var node = button.part.adornedPart; e.diagram.commandHandler.editTextBlock(node.findObject("TEXTBLOCK")); } // used by nextColor as the list of colors through which we rotate var myColors = ["lightgray", "lightblue", "lightgreen", "yellow", "orange", "pink"]; // used by both the Button Binding and by the changeColor click function function nextColor(c) { var idx = myColors.indexOf(c); if (idx < 0) return "lightgray"; if (idx >= myColors.length - 1) idx = 0; return myColors[idx + 1]; } function changeColor(e, button) { var node = button.part.adornedPart; var shape = node.findObject("SHAPE"); if (shape === null) return; node.diagram.startTransaction("Change color"); shape.fill = nextColor(shape.fill); button["_buttonFillNormal"] = nextColor(shape.fill); // update the button too node.diagram.commitTransaction("Change color"); } function drawLink(e, button) { var node = button.part.adornedPart; var tool = e.diagram.toolManager.linkingTool; tool.startObject = node.port; e.diagram.currentTool = tool; tool.doActivate(); } // used by both clickNewNode and dragNewNode to create a node and a link // from a given node to the new node function createNodeAndLink(data, fromnode) { var diagram = fromnode.diagram; var model = diagram.model; var nodedata = model.copyNodeData(data); model.addNodeData(nodedata); var newnode = diagram.findNodeForData(nodedata); var linkdata = model.copyLinkData({}); model.setFromKeyForLinkData(linkdata, model.getKeyForNodeData(fromnode.data)); model.setToKeyForLinkData(linkdata, model.getKeyForNodeData(newnode.data)); model.addLinkData(linkdata); diagram.select(newnode); return newnode; } // the Button.click event handler, called when the user clicks the "N" button function clickNewNode(e, button) { var data = button._dragData; if (!data) return; e.diagram.startTransaction("Create Node and Link"); var fromnode = button.part.adornedPart; var newnode = createNodeAndLink(button._dragData, fromnode); newnode.location = new go.Point(fromnode.location.x + 200, fromnode.location.y); e.diagram.commitTransaction("Create Node and Link"); } // the Button.actionMove event handler, called when the user drags within the "N" button function dragNewNode(e, button) { var tool = e.diagram.toolManager.draggingTool; if (tool.isBeyondDragSize()) { var data = button._dragData; if (!data) return; e.diagram.startTransaction("button drag"); // see doDeactivate, below var newnode = createNodeAndLink(data, button.part.adornedPart); newnode.location = e.diagram.lastInput.documentPoint; // don't commitTransaction here, but in tool.doDeactivate, after drag operation finished // set tool.currentPart to a selected movable Part and then activate the DraggingTool tool.currentPart = newnode; e.diagram.currentTool = tool; tool.doActivate(); } } // using dragNewNode also requires modifying the standard DraggingTool so that it // only calls commitTransaction when dragNewNode started a "button drag" transaction; // do this by overriding DraggingTool.doDeactivate: myDiagram.toolManager.draggingTool.doDeactivate = function() { // method override must be function, not => // commit "button drag" transaction, if it is ongoing; see dragNewNode, above if (this.diagram.undoManager.nestedTransactionNames.elt(0) === "button drag") { this.diagram.commitTransaction(); } go.DraggingTool.prototype.doDeactivate.call(this); // call the base method }; myDiagram.model = new go.GraphLinksModel( [ { key: 1, text: "Alpha", color: "lightblue", location: "0 0" }, { key: 2, text: "Beta", color: "orange", location: "140 0" }, { key: 3, text: "Gamma", color: "lightgreen", location: "0 140" }, { key: 4, text: "Delta", color: "pink", location: "140 140" } ], [ { from: 1, to: 2 } ]); myDiagram.findNodeForKey(4).isSelected = true; } window.addEventListener('DOMContentLoaded', init); </script> <div id="sample"> <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div> <p> The node template uses a custom <a>Part.selectionAdornmentTemplate</a> to add a row of Buttons when the node is selected. Select a node and you will see the Buttons for the node. </p> <p> The first button, "T", when clicked, starts in-place editing of the text. </p> <p> The second button, "C", when clicked, changes the color of the node, rotating through a list of colors. </p> <p> The third button, "L", when clicked or dragged, starts the <a>LinkingTool</a>, drawing a new link starting at the selected node. </p> <p> The fourth button, "N", when clicked, adds a new node and creates a link from the selected node to the new node. Dragging from the fourth button does the same thing as a click but also activates the <a>DraggingTool</a>, allowing the user to drag the new node where they like. </p> </div> </div> <!-- * * * * * * * * * * * * * --> <!-- End of GoJS sample code --> </div> </body> <!-- This script is part of the gojs.net website, and is not needed to run the sample --> <script src="../assets/js/goSamples.js"></script> </html>