Network Graph Visualization Online: Keep the Isolated Node
HTML for this example
Select the code and use your copy shortcut. Changes in this preview are temporary.
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Network Graph Visualization Online: Keep the Isolated Node</title><style>*{box-sizing:border-box}body{margin:0;color:var(--ink,#233342);background:var(--bg,#eef2f3);font:17px/1.6 system-ui,sans-serif}main{max-width:980px;margin:auto;padding:clamp(16px,4vw,38px)}h1{font:700 clamp(30px,5vw,49px)/1.12 Georgia,serif;margin:10px 0 20px;max-width:800px}h2{font-size:24px;line-height:1.3;margin:0 0 15px}h3{font-size:19px;margin:12px 0}p{margin:0 0 16px}.eyebrow{font-weight:750;letter-spacing:.08em;text-transform:uppercase;font-size:16px}header{padding:10px 0 25px;border-bottom:3px solid var(--accent,#24586d);margin-bottom:24px}.lede{font-size:20px;max-width:760px}.panel{background:var(--paper,#fff);padding:clamp(18px,3vw,28px);border:1px solid var(--line,#c6d1d8);border-radius:12px;margin:20px 0}.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:20px}.grid>*{min-width:0}.row{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin:16px 0}.stack>*{margin:12px 0}button{font:700 17px/1.4 system-ui,sans-serif;cursor:pointer;color:white;background:var(--accent,#24586d);border:2px solid var(--accent,#24586d);border-radius:7px;padding:11px 17px;max-width:100%;overflow-wrap:anywhere}button.secondary{background:transparent;color:var(--ink,#233342)}button[aria-pressed=true]{box-shadow:inset 0 0 0 3px #fff;outline:2px solid var(--ink,#233342)}button:disabled{opacity:.55;cursor:default}input,textarea,select{font:17px/1.5 system-ui,sans-serif;color:inherit;background:white;border:1px solid #778591;padding:10px 12px;border-radius:6px;max-width:100%;width:100%;min-width:0}input[type=checkbox]{width:22px;height:22px}textarea{min-height:110px;resize:vertical}label{display:block;font-weight:700;margin:12px 0 7px}button:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible{outline:3px solid #aa3d70;outline-offset:4px}.result{padding:18px;border-left:5px solid var(--accent,#24586d);background:var(--soft,#e5eff2);white-space:pre-wrap;overflow-wrap:anywhere;margin:20px 0}.result:empty{display:none}.hint{font-size:16px;color:var(--muted,#435968)}table{border-collapse:collapse;width:100%;table-layout:fixed;margin:16px 0}th,td{text-align:left;vertical-align:top;overflow-wrap:anywhere;padding:12px 8px;border-bottom:1px solid var(--line,#c6d1d8)}caption{text-align:left;font-weight:750;margin:8px 0}details{padding:18px;border:1px dashed #7b8b96;margin:20px 0}summary{cursor:pointer;font-weight:750}pre{font:16px/1.6 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere;background:#162735;color:#f5f8fa;padding:18px;border-radius:8px}canvas,svg{display:block;max-width:100%;height:auto}footer{margin:28px 0;font-size:16px}.badge{font-weight:750;color:var(--accent,#24586d)}.metric{font:700 38px/1.3 Georgia,serif}.board{display:grid;gap:5px;max-width:440px;margin:20px auto}.board button{padding:7px;min-height:45px}.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}@media(max-width:560px){.grid{grid-template-columns:1fr}main{padding:16px}th,td{padding:10px 5px}.row button{flex-grow:1}.metric{font-size:32px}}
:root{--bg:#e9f0ef;--paper:#fff;--accent:#2c6a63;--soft:#dfeee9;--ink:#29433c}.graph{background:#f2f8f4;border-radius:10px}svg text{font:700 28px system-ui;fill:#183f38}svg circle{fill:#e2ebcb;stroke:#3c7769;stroke-width:3}svg line{stroke:#6b9387;stroke-width:3}[hidden]{display:none!important}</style></head><body><main><header><p class="eyebrow">Graph explorer · Undirected and unweighted</p><h1>Network Graph Visualization Online: Keep the Isolated Node</h1><p class="lede">F has no edges, but it still belongs to the supplied graph.</p><p class="hint">Original six-node simple graph. This page calculates adjacency and paths locally; it performs no network discovery or scan.</p></header><div class="grid"><section class="panel"><h2>Explicit graph source</h2><label for="nodes">Node inventory</label><input id="nodes" value="A B C D E F"><label for="edges">Undirected edge pairs, one per line</label><textarea id="edges" rows="6">A B
A C
B D
C D
D E</textarea><label for="startNode">Source node</label><input id="startNode" value="A"><label for="endNode">Destination node</label><input id="endNode" value="E"><div class="row"><button id="calculate" type="button">Calculate graph</button><button id="delete" type="button">Delete B–D</button><button id="move" type="button">Move D (layout only)</button><button id="reset" type="button" class="secondary">Reset</button></div></section><section class="panel"><h2>Drawing · Not distance</h2><svg id="graph" class="graph" viewBox="0 0 420 300" role="img" aria-label="Six-node graph; read the adjacency and path results for relationships"><line id="edgeAB"/><line id="edgeAC"/><line id="edgeAD"/><line id="edgeAE"/><line id="edgeAF"/><line id="edgeBC"/><line id="edgeBD"/><line id="edgeBE"/><line id="edgeBF"/><line id="edgeCD"/><line id="edgeCE"/><line id="edgeCF"/><line id="edgeDE"/><line id="edgeDF"/><line id="edgeEF"/><g id="nodeA"><circle r="24"/><text text-anchor="middle" dy="7">A</text></g><g id="nodeB"><circle r="24"/><text text-anchor="middle" dy="7">B</text></g><g id="nodeC"><circle r="24"/><text text-anchor="middle" dy="7">C</text></g><g id="nodeD"><circle r="24"/><text text-anchor="middle" dy="7">D</text></g><g id="nodeE"><circle r="24"/><text text-anchor="middle" dy="7">E</text></g><g id="nodeF"><circle r="24"/><text text-anchor="middle" dy="7">F</text></g></svg><p id="layout">D layout at (240,145). Graph relationships unchanged by layout movement.</p></section></div><section class="panel"><h2>Graph results</h2><p id="result" class="result" role="status">Calculation pending.</p><pre id="adjacency"></pre><pre id="trace"></pre><p id="path" class="result"></p></section><footer>Move D, then delete B–D and recalculate. Only the edge change alters the graph.</footer></main><script>
(()=>{'use strict';const $=id=>document.getElementById(id);
const inventory=['A','B','C','D','E','F'];let currentEdges=null,moved=false;function coords(){return{A:[55,145],B:[145,70],C:[145,225],D:[240,moved?200:145],E:[350,145],F:[350,265]};}function draw(){const xy=coords();for(const k of inventory)$('node'+k).setAttribute('transform','translate('+xy[k].join(',')+')');for(let i=0;i<6;i++)for(let j=i+1;j<6;j++){const pair=inventory[i]+inventory[j],el=$('edge'+pair),active=currentEdges?.has(pair);el.style.display=active?'':'none';el.setAttribute('x1',xy[inventory[i]][0]);el.setAttribute('y1',xy[inventory[i]][1]);el.setAttribute('x2',xy[inventory[j]][0]);el.setAttribute('y2',xy[inventory[j]][1]);}$('layout').textContent='D layout at ('+xy.D.join(',')+'). Graph relationships unchanged by layout movement.';}function invalidate(){$('result').textContent='Source changed. Calculation pending.';$('adjacency').textContent='';$('trace').textContent='';$('path').textContent='';currentEdges=null;draw();}for(const k of ['nodes','edges','startNode','endNode'])$(k).addEventListener('input',invalidate);$('calculate').addEventListener('click',()=>{try{const nodes=$('nodes').value.trim().split(/\s+/);if(nodes.length!==6||new Set(nodes).size!==6||nodes.some(k=>!inventory.includes(k)))throw Error('List each node A–F exactly once.');const edges=new Set(),adj=Object.fromEntries(inventory.map(k=>[k,[]]));for(const line of $('edges').value.split(/\r?\n/).filter(x=>x.trim())){const p=line.trim().split(/\s+/);if(p.length!==2||p.some(k=>!inventory.includes(k)))throw Error('Each edge needs two declared A–F endpoints.');if(p[0]===p[1])throw Error('Self-edges are outside this simple graph.');const key=p.slice().sort().join('');if(edges.has(key))throw Error('Duplicate undirected pair '+key+'.');edges.add(key);adj[p[0]].push(p[1]);adj[p[1]].push(p[0]);}for(const a of Object.values(adj))a.sort();const source=$('startNode').value.trim().toUpperCase(),target=$('endNode').value.trim().toUpperCase();if(!inventory.includes(source)||!inventory.includes(target))throw Error('Source and destination must be declared A–F nodes.');const queue=[source],seen=new Set(queue),parents={},distance={[source]:0},trace=[];for(let i=0;i<queue.length;i++){const n=queue[i],added=[];for(const next of adj[n])if(!seen.has(next)){seen.add(next);parents[next]=n;distance[next]=distance[n]+1;queue.push(next);added.push(next);}trace.push('Process '+n+'; discover '+(added.join(',')||'none')+'; queue '+(queue.slice(i+1).join(',')||'empty'));}let components=0;const all=new Set();for(const node of inventory)if(!all.has(node)){components++;const q=[node];all.add(node);for(let i=0;i<q.length;i++)for(const next of adj[q[i]])if(!all.has(next)){all.add(next);q.push(next);}}const sum=inventory.reduce((n,k)=>n+adj[k].length,0);$('result').textContent='Nodes 6; edges '+edges.size+'; degree sum '+sum+' = 2 × '+edges.size+'; components '+components+'.';$('adjacency').textContent=inventory.map(k=>k+': '+(adj[k].join(', ')||'None')+' · degree '+adj[k].length+' · level '+(distance[k]??'Unreachable')).join('\n');$('trace').textContent=trace.join('\n');if(distance[target]===undefined)$('path').textContent=source+' → '+target+': Unreachable, not zero hops.';else{const p=[target];while(p[0]!==source)p.unshift(parents[p[0]]);$('path').textContent='Representative path: '+p.join(' → ')+'; '+distance[target]+' hops. Equal-length alternatives may exist.';}currentEdges=edges;draw();}catch(error){invalidate();$('result').textContent='Cannot calculate: '+error.message;}});$('delete').addEventListener('click',()=>{$('edges').value=$('edges').value.split(/\r?\n/).filter(line=>!['B D','D B'].includes(line.trim().replace(/\s+/g,' '))).join('\n');invalidate();});$('move').addEventListener('click',()=>{moved=!moved;draw();});$('reset').addEventListener('click',()=>{$('nodes').value='A B C D E F';$('edges').value='A B\nA C\nB D\nC D\nD E';$('startNode').value='A';$('endNode').value='E';moved=false;invalidate();});draw();
})();
</script></body></html>