UNPKG

create-gojs-kit

Version:

A CLI for downloading GoJS samples, extensions, and docs

400 lines (359 loc) 16.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="Support link connections within a node as well as between nodes." /> <meta itemprop="description" content="Support link connections within a node as well as between nodes." /> <meta property="og:description" content="Support link connections within a node as well as between nodes." /> <meta name="twitter:description" content="Support link connections within a node as well as between nodes." /> <link rel="preconnect" href="https://rsms.me/"> <link rel="stylesheet" href="../assets/css/style.css"> <!-- Copyright 1998-2025 by Northwoods Software Corporation. --> <meta itemprop="name" content="Connection Box Editor with Custom Link Validation" /> <meta property="og:title" content="Connection Box Editor with Custom Link Validation" /> <meta name="twitter:title" content="Connection Box Editor with Custom Link Validation" /> <meta property="og:image" content="https://gojs.net/latest/assets/images/screenshots/connectionboxnode.png" /> <meta itemprop="image" content="https://gojs.net/latest/assets/images/screenshots/connectionboxnode.png" /> <meta name="twitter:image" content="https://gojs.net/latest/assets/images/screenshots/connectionboxnode.png" /> <meta property="og:url" content="https://gojs.net/latest/samples/connectionBoxNode.html" /> <meta property="twitter:url" content="https://gojs.net/latest/samples/connectionBoxNode.html" /> <meta name="twitter:card" content="summary_large_image" /> <meta property="og:type" content="website" /> <meta property="twitter:domain" content="gojs.net" /> <title> Connection Box Editor with Custom Link Validation | GoJS Diagramming Library </title> </head> <body> <!-- This top nav is not part of the sample code --> <nav id="navTop" class=" w-full h-[var(--topnav-h)] z-30 bg-white border-b border-b-gray-200"> <div class="max-w-screen-xl mx-auto flex flex-wrap items-start justify-between px-4"> <a class="text-white bg-nwoods-primary font-bold !leading-[calc(var(--topnav-h)_-_1px)] my-0 px-2 text-4xl lg:text-5xl logo" href="../"> GoJS </a> <div class="relative"> <button id="topnavButton" class="h-[calc(var(--topnav-h)_-_1px)] px-2 m-0 text-gray-900 bg-inherit shadow-none md:hidden hover:!bg-inherit hover:!text-nwoods-accent hover:!shadow-none" aria-label="Navigation"> <svg class="h-7 w-7 block" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"> <path d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> <div id="topnavList" class="hidden md:block"> <div class="absolute right-0 z-30 flex flex-col items-end rounded border border-gray-200 p-4 pl-12 shadow bg-white text-gray-900 font-semibold md:flex-row md:space-x-4 md:items-start md:border-0 md:p-0 md:shadow-none md:bg-inherit"> <a href="../learn/">Learn</a> <a href="../samples/">Samples</a> <a href="../intro/">Intro</a> <a href="../api/">API</a> <a href="../download.html">Download</a> <a href="https://forum.nwoods.com/c/gojs/11" target="_blank" rel="noopener">Forum</a> <a id="tc" href="https://nwoods.com/contact.html" target="_blank" rel="noopener" onclick="getOutboundLink('https://nwoods.com/contact.html', 'contact');">Contact</a> <a id="tb" href="https://nwoods.com/sales/index.html" target="_blank" rel="noopener" onclick="getOutboundLink('https://nwoods.com/sales/index.html', 'buy');">Buy</a> </div> </div> </div> </div> </nav> <script> window.addEventListener("DOMContentLoaded", function () { // topnav var topButton = document.getElementById("topnavButton"); var topnavList = document.getElementById("topnavList"); if (topButton && topnavList) { topButton.addEventListener("click", function (e) { topnavList .classList .toggle("hidden"); e.stopPropagation(); }); document.addEventListener("click", function (e) { // if the clicked element isn't the list, close the list if (!topnavList.classList.contains("hidden") && !e.target.closest("#topnavList")) { topButton.click(); } }); // set active <a> element var url = window .location .href .toLowerCase(); var aTags = topnavList.getElementsByTagName('a'); for (var i = 0; i < aTags.length; i++) { var lowerhref = aTags[i] .href .toLowerCase(); if (lowerhref.endsWith('.html')) lowerhref = lowerhref.slice(0, -5); if (url.startsWith(lowerhref)) { aTags[i] .classList .add('active'); break; } } } }); </script> <div class="flex flex-col prose"> <div class="w-full max-w-screen-xl mx-auto"> <!-- * * * * * * * * * * * * * --> <!-- Start of GoJS sample code --> <script src="https://cdn.jsdelivr.net/npm/gojs@3.1.0"></script> <link rel="stylesheet" href="../assets/css/prism.css"/> <script src="../assets/js/prism.js"></script> <div id="allSampleContent" class="p-4 w-full"> <script id="code"> function init() { myDiagram = new go.Diagram('myDiagramDiv', { initialContentAlignment: go.Spot.Center, // for v1.* initialScale: 1.4, 'undoManager.isEnabled': true, 'linkingTool.direction': go.LinkingDirection.ForwardsOnly, ModelChanged: e => { // just for demonstration purposes, if (e.isTransactionFinished) { // show the model data in the page's TextArea document.getElementById('mySavedModel').innerHTML = e.model.toJson(); if (window.Prism) window.Prism.highlightAll(); } } }); myDiagram.nodeTemplate = new go.Node('Table', { selectionObjectName: 'BODY', linkValidation: (fromnode, fromport, tonode, toport, link) => { if (!fromport || !toport) return false; if (fromnode === tonode) { // inside a node must go from an input port to an output port return fromport.portId[0] === 'i' && toport.portId[0] === 'o'; } else { // between nodes the port colors must match if (fromport.fill !== toport.fill) return false; // between nodes must go from an output port to an input port return fromport.portId[0] === 'o' && toport.portId[0] === 'i'; } return true; } }) .bindTwoWay('location', 'location', go.Point.parse, go.Point.stringify) .addColumnDefinition(1, { width: 70 }) .add( new go.Shape({ name: 'BODY', row: 0, rowSpan: 99, column: 0, columnSpan: 3, stretch: go.Stretch.Fill, fill: 'gray', strokeWidth: 0, margin: new go.Margin(0, 8) }), new go.TextBlock({ row: 0, columnSpan: 3, margin: new go.Margin(4, 2, 2, 2) }) .bind('text'), new go.TextBlock({ row: 2, columnSpan: 3, margin: new go.Margin(4, 2, 2, 2) }) .bind('text', 'text2'), new go.Panel('Table', { row: 1, column: 0, defaultSeparatorPadding: new go.Margin(4, 0), // input ports itemTemplate: new go.Panel('TableRow', { background: 'white' }) .add( new go.Shape({ width: 6, height: 6, strokeWidth: 0, margin: new go.Margin(2, 6, 2, 0), fromSpot: go.Spot.Right, toSpot: go.Spot.Left, fromLinkable: true, toLinkable: true, fromLinkableSelfNode: true, toLinkableSelfNode: true, cursor: 'pointer' }) .bindObject('portId', 'row', r => 'i' + r) .bind('fill', '', convertToColor) ) }) .bind('itemArray', 'inPorts'), new go.Shape({ row: 1, column: 1, fill: 'white', strokeWidth: 0, stretch: go.Stretch.Fill }), new go.Panel('Table', { row: 1, column: 2, defaultSeparatorPadding: new go.Margin(4, 0), // output ports itemTemplate: new go.Panel('TableRow', { background: 'white' }) .add( new go.Shape({ width: 6, height: 6, strokeWidth: 0, margin: new go.Margin(2, 0, 2, 6), fromSpot: go.Spot.Right, toSpot: go.Spot.Left, fromLinkable: true, toLinkable: true, fromLinkableSelfNode: true, toLinkableSelfNode: true, cursor: 'pointer' }) .bindObject('portId', 'row', r => 'o' + r) .bind('fill', '', convertToColor) ) }) .bind('itemArray', 'outPorts') ); function convertToColor(n) { switch (n) { case 'r': return 'brown'; case 'g': return 'olivedrab'; case 'b': return 'cornflowerblue'; default: return 'black'; } } myDiagram.linkTemplate = new go.Link({ corner: 10, relinkableFrom: true, relinkableTo: true }) .add( new go.Shape({ strokeWidth: 2 }) .bindObject('stroke', 'fromPort', p => p.fill) ); myDiagram.model = new go.GraphLinksModel({ linkFromPortIdProperty: 'fpid', linkToPortIdProperty: 'tpid', copiesArrays: true, copiesArrayObjects: true, nodeDataArray: [ { key: 1, text: 'Alpha', location: '0 0', inPorts: ['r', 'r', 'r', 'g', 'b'], outPorts: ['r', 'g', 'g', 'b', 'b'] }, { key: 2, text: 'Beta', location: '200 -80', inPorts: ['r', 'r', 'g', 'g', 'b'], outPorts: ['r', 'r', 'g', 'g', 'b'] }, { key: 3, text: 'Gamma', location: '200 80', inPorts: ['r', 'r', 'g', 'g', 'b'], outPorts: ['r', 'r', 'g', 'g', 'b'] } ], linkDataArray: [ { from: 1, fpid: 'i0', to: 1, tpid: 'o1' }, { from: 1, fpid: 'i1', to: 1, tpid: 'o4' }, { from: 1, fpid: 'i2', to: 1, tpid: 'o0' }, { from: 1, fpid: 'i3', to: 1, tpid: 'o3' }, { from: 1, fpid: 'i4', to: 1, tpid: 'o2' }, { from: 1, fpid: 'o0', to: 2, tpid: 'i0' }, { from: 1, fpid: 'o2', to: 2, tpid: 'i2' }, { from: 1, fpid: 'o2', to: 3, tpid: 'i2' }, { from: 1, fpid: 'o3', to: 2, tpid: 'i4' }, { from: 1, fpid: 'o3', to: 3, tpid: 'i4' }, { from: 2, fpid: 'i0', to: 2, tpid: 'o1' }, { from: 2, fpid: 'i2', to: 2, tpid: 'o0' }, { from: 2, fpid: 'i4', to: 2, tpid: 'o2' }, { from: 3, fpid: 'i2', to: 3, tpid: 'o3' }, { from: 3, fpid: 'i1', to: 3, tpid: 'o1' } ] }); } window.addEventListener('DOMContentLoaded', init); </script> <div id="sample"> <div id="myDiagramDiv" style="border: solid 1px black; width: 100%; height: 600px"></div> <p> You can draw new links between ports, both between nodes and within a node. Between nodes, the link validation predicate requires new link connections to connect ports of the same color. However, within a node, links may connect ports of different colors. </p> <pre class="lang-js" style="max-height: 250px;"><code id="mySavedModel"></code></pre> </div> </div> <!-- * * * * * * * * * * * * * --> <!-- End of GoJS sample code --> </div> <div id="allTagDescriptions" class="p-4 w-full max-w-screen-xl mx-auto"> <hr/> <h3 class="text-xl">GoJS Features in this sample</h3> <!-- blacklist tags that do not correspond to a specific GoJS feature --> <h4>Table Panels</h4> <p> The "Table" Panel, <a href="../api/symbols/Panel.html#static-Table" target="api">Panel.Table</a>, arranges objects in rows and columns. Each object in a Table Panel is put into the cell indexed by the value of <a href="../api/symbols/GraphObject.html#row" target="api">GraphObject.row</a> and <a href="../api/symbols/GraphObject.html#column" target="api">GraphObject.column</a>. The panel will look at the rows and columns for all of the objects in the panel to determine how many rows and columns the table should have. More information can be found in the <a href="../intro/tablePanels.html">GoJS Intro</a>. </p> <p> <a href="../samples/index.html#tables">Related samples</a> </p> <hr> <!-- blacklist tags that do not correspond to a specific GoJS feature --> <h4>Item Arrays</h4> <p> It is sometimes useful to display a variable number of elements in a node by data binding to a JavaScript Array. In GoJS, this is simply achieved by binding (or setting) <a href="../api/symbols/Panel.html#itemArray" target="api">Panel.itemArray</a>. The <a href="../api/symbols/Panel.html" target="api">Panel</a> will create an element in the panel for each value in the Array. More information can be found in the <a href="../intro/itemArrays.html">GoJS Intro</a>. </p> <p> <a href="../samples/index.html#itemarrays">Related samples</a> </p> <hr> <!-- blacklist tags that do not correspond to a specific GoJS feature --> <h4>Links</h4> <p> The <a href="../api/symbols/Link.html" target="api">Link</a> class is used to implement a visual relationship between nodes. Links are normally created by the presence of link data objects in the <a href="../api/symbols/GraphLinksModel.html#linkDataArray" target="api">GraphLinksModel.linkDataArray</a> or by a parent key reference as the value of the <a href="../api/symbols/TreeModel.html#nodeParentKeyProperty" target="api">TreeModel.nodeParentKeyProperty</a> of a node data object in a <a href="../api/symbols/TreeModel.html" target="api">TreeModel</a>. More information can be found in the <a href="../intro/links.html">GoJS Intro</a>. </p> <p> <a href="../samples/index.html#links">Related samples</a> </p> <hr> <!-- blacklist tags that do not correspond to a specific GoJS feature --> <h4>Ports in Nodes</h4> <p> Specific elements of a Node at which links may connect are called <i>ports</i>. There may be any number of ports in a node. By default there is just one port, the whole node, which results in the effect of having the whole node act as the port. Port-like GraphObjects can only be in <a href="../api/symbols/Node.html" target="api">Node</a>s or <a href="../api/symbols/Group.html" target="api">Group</a>s, not in <a href="../api/symbols/Link.html" target="api">Link</a>s or <a href="../api/symbols/Adornment.html" target="api">Adornment</a>s or simple <a href="../api/symbols/Part.html" target="api">Part</a>s. </p> <p> More information can be found in the <a href="../intro/ports.html">GoJS Intro</a>. </p> <p> <a href="../samples/index.html#ports">Related samples</a> </p> <hr> </div> </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>