UNPKG

create-gojs-kit

Version:

A CLI for downloading GoJS samples, extensions, and docs

616 lines (557 loc) 24.4 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="Interactive flowchart diagram implemented by GoJS in JavaScript for HTML." /> <meta itemprop="description" content="Interactive flowchart diagram implemented by GoJS in JavaScript for HTML." /> <meta property="og:description" content="Interactive flowchart diagram implemented by GoJS in JavaScript for HTML." /> <meta name="twitter:description" content="Interactive flowchart diagram implemented by GoJS in JavaScript for HTML." /> <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="Interactive Diagram for Building Flowcharts" /> <meta property="og:title" content="Interactive Diagram for Building Flowcharts" /> <meta name="twitter:title" content="Interactive Diagram for Building Flowcharts" /> <meta property="og:image" content="https://gojs.net/latest/assets/images/screenshots/flowchart.png" /> <meta itemprop="image" content="https://gojs.net/latest/assets/images/screenshots/flowchart.png" /> <meta name="twitter:image" content="https://gojs.net/latest/assets/images/screenshots/flowchart.png" /> <meta property="og:url" content="https://gojs.net/latest/samples/flowchart.html" /> <meta property="twitter:url" content="https://gojs.net/latest/samples/flowchart.html" /> <meta name="twitter:card" content="summary_large_image" /> <meta property="og:type" content="website" /> <meta property="twitter:domain" content="gojs.net" /> <title> Interactive Diagram for Building Flowcharts | 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> <div id="allSampleContent" class="p-4 w-full"> <link href="https://fonts.googleapis.com/css?family=Figtree:400,600&subset=latin,latin-ext" rel="stylesheet" type="text/css" /> <style> #hidden { font: 600 18px Figtree; opacity: 0; } </style> <script id="code"> function init() { myDiagram = new go.Diagram('myDiagramDiv', { 'undoManager.isEnabled': true, // enable undo & redo 'themeManager.changesDivBackground': true, 'themeManager.currentTheme': document.getElementById('theme').value }); // when the document is modified, add a "*" to the title and enable the "Save" button myDiagram.addDiagramListener('Modified', e => { const button = document.getElementById('SaveButton'); if (button) button.disabled = !myDiagram.isModified; const idx = document.title.indexOf('*'); if (myDiagram.isModified) { if (idx < 0) document.title += '*'; } else { if (idx >= 0) document.title = document.title.slice(0, idx); } }); // set up some colors/fonts for the default ('light') and dark Themes myDiagram.themeManager.set('light', { colors: { text: '#fff', start: '#064e3b', step: '#49939e', conditional: '#6a9a8a', end: '#7f1d1d', comment: '#a691cc', bgText: '#000', link: '#dcb263', linkOver: '#cbd5e1', div: '#ede9e0' } }); myDiagram.themeManager.set('dark', { colors: { text: '#fff', step: '#414a8d', conditional: '#88afa2', comment: '#bfb674', bgText: '#fff', link: '#fdb71c', linkOver: '#475569', div: '#141e37' } }); defineFigures(); // helper definitions for node templates function nodeStyle(node) { node // the Node.location is at the center of each node .set({ locationSpot: go.Spot.Center }) // The Node.location comes from the "loc" property of the node data, // converted by the Point.parse static method. // If the Node.location is changed, it updates the "loc" property of the node data, // converting back using the Point.stringify static method. .bindTwoWay('location', 'loc', go.Point.parse, go.Point.stringify); } function shapeStyle(shape) { // make the whole node shape a port shape.set({ strokeWidth: 0, portId: '', cursor: 'pointer' }); } function textStyle(textblock) { textblock .set({ font: 'bold 11pt Figtree, sans-serif' }) .theme('stroke', 'text'); } // define the Node templates for regular nodes myDiagram.nodeTemplateMap.add('', // the default category new go.Node('Auto') .apply(nodeStyle) .add( new go.Shape('Rectangle', { fromLinkable: true, toLinkable: true, fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides }) .apply(shapeStyle) .theme('fill', 'step'), new go.TextBlock({ margin: 12, maxSize: new go.Size(160, NaN), wrap: go.Wrap.Fit, editable: true }) .apply(textStyle) .bindTwoWay('text') ) ); myDiagram.nodeTemplateMap.add('Conditional', new go.Node('Auto') .apply(nodeStyle) .add( new go.Shape('Conditional', { fromLinkable: true, toLinkable: true }) .apply(shapeStyle) .theme('fill', 'conditional'), new go.TextBlock({ margin: 8, maxSize: new go.Size(160, NaN), wrap: go.Wrap.Fit, textAlign: 'center', editable: true }) .apply(textStyle) .bindTwoWay('text') ) ); myDiagram.nodeTemplateMap.add('Start', new go.Node('Auto') .apply(nodeStyle) .add( new go.Shape('Capsule', { fromLinkable: true }) .apply(shapeStyle) .theme('fill', 'start'), new go.TextBlock('Start', { margin: new go.Margin(5, 6) }) .apply(textStyle) .bind('text') ) ); myDiagram.nodeTemplateMap.add('End', new go.Node('Auto') .apply(nodeStyle) .add( new go.Shape('Capsule', { toLinkable: true }) .apply(shapeStyle) .theme('fill', 'end'), new go.TextBlock('End', { margin: new go.Margin(5, 6) }) .apply(textStyle) .bind('text') ) ); myDiagram.nodeTemplateMap.add('Comment', new go.Node('Auto') .apply(nodeStyle) .add( new go.Shape('File', { strokeWidth: 3 }) .theme('fill', 'div') .theme('stroke', 'comment'), new go.TextBlock({ font: '9pt Figtree, sans-serif', margin: 8, maxSize: new go.Size(200, NaN), wrap: go.Wrap.Fit, textAlign: 'center', editable: true }) .theme('stroke', 'bgText') .bindTwoWay('text') // no ports, because no links are allowed to connect with a comment ) ); // replace the default Link template in the linkTemplateMap myDiagram.linkTemplate = new go.Link({ routing: go.Routing.AvoidsNodes, curve: go.Curve.JumpOver, corner: 5, toShortLength: 4, relinkableFrom: true, relinkableTo: true, reshapable: true, resegmentable: true, // mouse-overs subtly highlight links: mouseEnter: (e, link) => (link.findObject('HIGHLIGHT').stroke = link.diagram.themeManager.findValue('linkOver', 'colors')), mouseLeave: (e, link) => (link.findObject('HIGHLIGHT').stroke = 'transparent'), // context-click creates an editable link label contextClick: (e, link) => { e.diagram.model.commit(m => { m.set(link.data, 'text', 'Label'); }); } }) .bindTwoWay('points') .add( // the highlight shape, normally transparent new go.Shape({ isPanelMain: true, strokeWidth: 8, stroke: 'transparent', name: 'HIGHLIGHT' }), // the link path shape new go.Shape({ isPanelMain: true, strokeWidth: 2 }) .theme('stroke', 'link'), // the arrowhead new go.Shape({ toArrow: 'standard', strokeWidth: 0, scale: 1.5 }) .theme('fill', 'link'), // the link label new go.Panel('Auto', { visible: false }) .bind('visible', 'text', t => typeof t === 'string' && t.length > 0) // only shown if there is text .add( // a gradient that fades into the background new go.Shape('Ellipse', { strokeWidth: 0 }) .theme('fill', 'div', null, null, c => new go.Brush("Radial", { 0: c, 0.5: `${c}00` })), new go.TextBlock({ name: 'LABEL', font: '9pt Figtree, sans-serif', margin: 3, editable: true }) .theme('stroke', 'bgText') .bindTwoWay('text') ) ); // temporary links used by LinkingTool and RelinkingTool are also orthogonal: myDiagram.toolManager.linkingTool.temporaryLink.routing = go.Routing.Orthogonal; myDiagram.toolManager.relinkingTool.temporaryLink.routing = go.Routing.Orthogonal; load(); // load an initial diagram from some JSON text // initialize the Palette that is on the left side of the page myPalette = new go.Palette('myPaletteDiv', { nodeTemplateMap: myDiagram.nodeTemplateMap, // share the templates used by myDiagram themeManager: myDiagram.themeManager, // share the ThemeManager used by myDiagram model: new go.GraphLinksModel([ // specify the contents of the Palette { category: 'Start', text: 'Start' }, { text: 'Step' }, { category: 'Conditional', text: '???' }, { category: 'End', text: 'End' }, { category: 'Comment', text: 'Comment' } ]) }); } // end init // define some custom shapes for node templates function defineFigures() { go.Shape.defineFigureGenerator('Conditional', (shape, w, h) => { const geo = new go.Geometry(); const fig = new go.PathFigure(w * 0.15, 0, true); geo.add(fig); fig.add(new go.PathSegment(go.SegmentType.Line, w * 0.85, 0)); fig.add(new go.PathSegment(go.SegmentType.Line, w, 0.5 * h)); fig.add(new go.PathSegment(go.SegmentType.Line, w * 0.85, h)); fig.add(new go.PathSegment(go.SegmentType.Line, w * 0.15, h)); fig.add(new go.PathSegment(go.SegmentType.Line, 0, 0.5 * h).close()); geo.spot1 = new go.Spot(0.15, 0); geo.spot2 = new go.Spot(0.85, 1); return geo; }); // taken from ../extensions/Figures.js: go.Shape.defineFigureGenerator('File', (shape, w, h) => { const geo = new go.Geometry(); const fig = new go.PathFigure(0, 0, true); // starting point geo.add(fig); fig.add(new go.PathSegment(go.SegmentType.Line, 0.75 * w, 0)); fig.add(new go.PathSegment(go.SegmentType.Line, w, 0.25 * h)); fig.add(new go.PathSegment(go.SegmentType.Line, w, h)); fig.add(new go.PathSegment(go.SegmentType.Line, 0, h).close()); const fig2 = new go.PathFigure(0.75 * w, 0, false); geo.add(fig2); // The Fold fig2.add(new go.PathSegment(go.SegmentType.Line, 0.75 * w, 0.25 * h)); fig2.add(new go.PathSegment(go.SegmentType.Line, w, 0.25 * h)); geo.spot1 = new go.Spot(0, 0.25); geo.spot2 = go.Spot.BottomRight; return geo; }); } // Show the diagram's model in JSON format that the user may edit function save() { document.getElementById('mySavedModel').value = myDiagram.model.toJson(); myDiagram.isModified = false; } function load() { myDiagram.model = go.Model.fromJson(document.getElementById('mySavedModel').value); } // print the diagram by opening a new window holding SVG images of the diagram contents for each page function printDiagram() { const svgWindow = window.open(); if (!svgWindow) return; // failure to open a new Window svgWindow.document.title = "GoJS Flowchart"; svgWindow.document.body.style.margin = "0px"; const printSize = new go.Size(700, 960); const bnds = myDiagram.documentBounds; let x = bnds.x; let y = bnds.y; while (y < bnds.bottom) { while (x < bnds.right) { const svg = myDiagram.makeSvg({ scale: 1.0, position: new go.Point(x, y), size: printSize, background: myDiagram.themeManager.findValue('div', 'colors') }); svgWindow.document.body.appendChild(svg); x += printSize.width; } x = bnds.x; y += printSize.height; } setTimeout(() => { svgWindow.print(); svgWindow.close(); }, 1); } function changeTheme() { const myDiagram = go.Diagram.fromDiv('myDiagramDiv'); if (myDiagram) { myDiagram.themeManager.currentTheme = document.getElementById('theme').value; } } window.addEventListener('DOMContentLoaded', () => { // setTimeout only to ensure font is loaded before loading diagram // you may want to use an asset loading library for this // to keep this sample simple, it does not setTimeout(() => { init(); }, 300); }); </script> <div id="sample"> <div class="sampleWrapper"> <div style="width: 100%; height: fit-content; display: flex; flex: 2"> <div id="myPaletteDiv" style="width: 100px; margin-right: 2px"></div> <div id="myDiagramDiv" style="flex-grow: 1; height: 810px"></div> </div> <div style="flex: 1; min-width: 425px"> Theme: <select id="theme" onchange="changeTheme()"> <option value="system">System</option> <option value="light">Light</option> <option value="dark" selected>Dark</option> </select> <p> The Flowchart sample demonstrates several key features of GoJS, namely <a href="../intro/palette.html">Palette</a>s, <a href="../intro/links.html">Linkable nodes</a>, Drag/Drop behavior, <a href="../intro/textBlocks.html">Text Editing</a>, and the use of <a href="../intro/templateMaps.html">Node Template Maps</a> in Diagrams. </p> <p> Drag from the edges of a Node to create new Links. Selecting Links allows you to re-shape and re-link them. Selecting a Node and then clicking its TextBlock will allow you to edit text (except on the Start and End Nodes). Context clicking a Link creates an editable link label. </p> <p>The dark and light themes are controlled using the <a>ThemeManager</a>.</p> <button onclick="printDiagram()">Print Diagram Using SVG</button> <br /> <button id="SaveButton" onclick="save()">Save</button> <button onclick="load()">Load</button> Diagram Model saved in JSON format: <textarea id="mySavedModel" style="width: 100%; height: 375px"> { "class": "GraphLinksModel", "pointsDigits": 0, "nodeDataArray": [ {"key":-1,"category":"Start","loc":"-237 41","text":"Start"}, {"key":-2,"category":"End","loc":"277 696","text":"End"}, {"category":"Conditional","text":"Is data\ntree-like?","key":-14,"loc":"40 165"}, {"text":"Use a TreeModel","key":-5,"loc":"-100 230"}, {"text":"Use a GraphLinksModel","key":-6,"loc":"180 230"}, {"category":"Comment","text":"GraphLinksModel\nalso allows Groups","key":-7,"loc":"362 230"}, {"text":"Create DIV for Diagram","key":-8,"loc":"-64 41"}, {"text":"Create new Diagram associated with DIV","key":-9,"loc":"164 41"}, {"text":"Style node templates","key":-10,"loc":"40 617"}, {"text":"Add data to node/linkDataArray","key":-12,"loc":"180 320"}, {"text":"Add data to nodeDataArray, including parent","key":-13,"loc":"-100 320"}, {"text":"Style link templates","key":-15,"loc":"277 617"}, {"category":"Conditional","text":"Should nodes be auto-positioned?","key":-16,"loc":"40 460"}, {"text":"Choose a layout","key":-18,"loc":"-100 525"}, {"text":"Set location in node data and bind","key":-17,"loc":"180 525"} ], "linkDataArray": [ {"from":-1,"to":-8}, {"from":-8,"to":-9}, {"from":-5,"to":-13}, {"from":-6,"to":-12}, {"from":-15,"to":-2}, {"from":-14,"to":-5,"text":"Yes"}, {"from":-14,"to":-6,"text":"No"}, {"from":-9,"to":-14}, {"from":-13,"to":-16}, {"from":-12,"to":-16}, {"from":-16,"to":-18,"text":"Yes"}, {"from":-16,"to":-17,"text":"No"}, {"from":-18,"to":-10}, {"from":-17,"to":-10}, {"from":-10,"to":-15} ]} </textarea> <p id="hidden" style="padding: 0; height: 0px">this forces the font to load in Chromium browsers</p> </div> </div> </div> <style> .sampleWrapper { display: flex; flex-direction: column; @media (min-width: 1280px) { flex-direction: row; } & > div:first-child { margin-bottom: 0.5rem; @media (min-width: 1280px) { margin-right: 0.5rem; margin-bottom: 0; } } } </style> </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>Palette</h4> <p> A <a href="../api/symbols/Palette.html" target="api">Palette</a> is a subclass of <a href="../api/symbols/Diagram.html" target="api">Diagram</a> that is used to display a number of <a href="../api/symbols/Part.html" target="api">Part</a>s that can be dragged into the diagram that is being modified by the user. The initialization of a <a href="../api/symbols/Palette.html" target="api">Palette</a> is just like the initialization of any <a href="../api/symbols/Diagram.html" target="api">Diagram</a>. Like Diagrams, you can have more than one Palette on the page at the same time. </p> <p> More information can be found in the <a href="../intro/palette.html">GoJS Intro</a>. </p> <p> <a href="../samples/index.html#palette">Related samples</a> </p> <hr> <!-- blacklist tags that do not correspond to a specific GoJS feature --> <h4>Exporting SVGs</h4> <p> <b>GoJS</b> has one function for creating SVG: <a href="../api/symbols/Diagram.html#makeSVG" target="api">Diagram.makeSVG</a>, which returns a new SVGElement with a representation of a GoJS Diagram. The method has a single argument, a JavaScript Object that contains several definable properties, enumerated in the documentation. More information can be found in the <a href="../intro/makingSVG.html">GoJS Intro</a>. </p> <p> <a href="../samples/index.html#svg">Related samples</a> </p> <hr> <!-- blacklist tags that do not correspond to a specific GoJS feature --> <!-- blacklist tags that do not correspond to a specific GoJS feature --> <h4>Theming</h4> <p> <b>GoJS</b> allows diagrams to be themed. This is commonly used to provide a light and dark mode for diagrams. </p> <p> The <a href="../api/symbols/Diagram.html#themeManager" target="api">Diagram.themeManager</a> handles themes within a <a href="../api/symbols/Diagram.html" target="api">Diagram</a>. The <a href="../api/symbols/ThemeManager.html" target="api">ThemeManager</a> can by shared by multiple diagrams, and is responsible to managing the current theme and default theme, along with any theme updates. More information can be found in the <a href="../intro/theming.html">GoJS Intro</a>. </p> <p> <a href="../samples/index.html#theme">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>