UNPKG

gojs

Version:

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

237 lines (222 loc) 11.8 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="In one diagram show the whole tree and in a second diagram show a subset that is logically near a selected node."/> <link rel="stylesheet" href="../assets/css/style.css"/> <!-- Copyright 1998-2023 by Northwoods Software Corporation. --> <title>Local View</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() { // 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 myFullDiagram = new go.Diagram("fullDiagram", // each diagram refers to its DIV HTML element by id { initialAutoScale: go.Diagram.UniformToFill, // automatically scale down to show whole tree maxScale: 0.25, contentAlignment: go.Spot.Center, // center the tree in the viewport isReadOnly: true, // don't allow user to change the diagram "animationManager.isEnabled": false, layout: $(go.TreeLayout, { angle: 90, sorting: go.TreeLayout.SortingAscending }), maxSelectionCount: 1, // only one node may be selected at a time in each diagram // when the selection changes, update the myLocalDiagram view "ChangedSelection": showLocalOnFullClick }); myLocalDiagram = // this is very similar to the full Diagram new go.Diagram("localDiagram", { autoScale: go.Diagram.UniformToFill, contentAlignment: go.Spot.Center, isReadOnly: true, layout: $(go.TreeLayout, { angle: 90, sorting: go.TreeLayout.SortingAscending }), "LayoutCompleted": e => { var sel = e.diagram.selection.first(); if (sel !== null) myLocalDiagram.scrollToRect(sel.actualBounds); }, maxSelectionCount: 1, // when the selection changes, update the contents of the myLocalDiagram "ChangedSelection": showLocalOnLocalClick }); // Define a node template that is shared by both diagrams var myNodeTemplate = $(go.Node, "Auto", { locationSpot: go.Spot.Center }, new go.Binding("text", "key", go.Binding.toString), // for sorting $(go.Shape, "Rectangle", new go.Binding("fill", "color"), { stroke: null }), $(go.TextBlock, { margin: 5 }, new go.Binding("text", "key", k => "node" + k)) ); myFullDiagram.nodeTemplate = myNodeTemplate; myLocalDiagram.nodeTemplate = myNodeTemplate; // Define a basic link template, not selectable, shared by both diagrams var myLinkTemplate = $(go.Link, { routing: go.Link.Normal, selectable: false }, $(go.Shape, { strokeWidth: 1 }) ); myFullDiagram.linkTemplate = myLinkTemplate; myLocalDiagram.linkTemplate = myLinkTemplate; // Create the full tree diagram setupDiagram(); // Create a part in the background of the full diagram to highlight the selected node highlighter = $(go.Part, "Auto", { layerName: "Background", selectable: false, isInDocumentBounds: false, locationSpot: go.Spot.Center }, $(go.Shape, "Ellipse", { fill: $(go.Brush, "Radial", { 0.0: "yellow", 1.0: "white" }), stroke: null, desiredSize: new go.Size(400, 400) }) ); myFullDiagram.add(highlighter); // Start by focusing the diagrams on the node at the top of the tree. // Wait until the tree has been laid out before selecting the root node. myFullDiagram.addDiagramListener("InitialLayoutCompleted", e => { var node0 = myFullDiagram.findPartForKey(0); if (node0 !== null) node0.isSelected = true; showLocalOnFullClick(); }); } // Make the corresponding node in the full diagram to that selected in the local diagram selected, // then call showLocalOnFullClick to update the local diagram. function showLocalOnLocalClick() { var selectedLocal = myLocalDiagram.selection.first(); if (selectedLocal !== null) { // there are two separate Nodes, one for each Diagram, but they share the same key value myFullDiagram.select(myFullDiagram.findPartForKey(selectedLocal.data.key)); } } function showLocalOnFullClick() { var node = myFullDiagram.selection.first(); if (node !== null) { // make sure the selected node is in the viewport myFullDiagram.scrollToRect(node.actualBounds); // move the large yellow node behind the selected node to highlight it highlighter.location = node.location; // create a new model for the local Diagram var model = new go.TreeModel(); // add the selected node and its children and grandchildren to the local diagram var nearby = node.findTreeParts(3); // three levels of the (sub)tree // add parent and grandparent var parent = node.findTreeParentNode(); if (parent !== null) { nearby.add(parent); var grandparent = parent.findTreeParentNode(); if (grandparent !== null) { nearby.add(grandparent); } } // create the model using the same node data as in myFullDiagram's model nearby.each(n => { if (n instanceof go.Node) model.addNodeData(n.data); }); myLocalDiagram.model = model; // select the node at the diagram's focus var selectedLocal = myLocalDiagram.findPartForKey(node.data.key); if (selectedLocal !== null) selectedLocal.isSelected = true; } } // Create the tree model containing TOTAL nodes, with each node having a variable number of children function setupDiagram(total) { if (total === undefined) total = 100; // default to 100 nodes var nodeDataArray = []; for (var i = 0; i < total; i++) { nodeDataArray.push({ key: nodeDataArray.length, color: go.Brush.randomColor() }); } var j = 0; for (var i = 1; i < total; i++) { var data = nodeDataArray[i]; data.parent = j; if (Math.random() < 0.3) j++; // this controls the likelihood that there are enough children } myFullDiagram.model = new go.TreeModel(nodeDataArray); } window.addEventListener('DOMContentLoaded', init); </script> <div id="sample"> <div id="fullDiagram" style="height:250px;width:100%;border:1px solid black;margin:2px"></div> <div id="localDiagram" style="height:350px;width:100%;border:1px solid black;margin:2px"></div> <button onclick="setupDiagram()">Create New Tree</button> <p> This sample includes two diagrams, the one on top showing a full tree and the one below focusing on a specific node in the tree and those nodes that are logically "near" it. When the selection changes in either diagram, the lower diagram changes its focus to the selected node. To show which node in the full tree is selected, a large yellow highlighter part employing a radial <a>Brush</a> is placed in the background layer of the upper diagram behind the selected node. The Create New Tree button will randomly generate a new <a>TreeModel</a> to be used by the diagrams. </p> <p> Although it is not demonstrated in this sample, one could well use very simple templates for Nodes and for Links in the top Diagram. This would make the top Diagram more efficient to construct when there are very many more nodes. And one could use more detailed templates in the bottom Diagram, where there is more room to show information for each node. </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>