@@ -14,19 +14,46 @@ <h1>Graph Viewer</h1>
1414 < main >
1515 < div id ="graph "> </ div >
1616 < aside class ="sidebar ">
17- < h2 > </ h2 >
18- < pre id ="node-details "> No node selected .</ pre >
17+ < h2 id =" sidebar-title " > No node selected </ h2 >
18+ < div id ="node-details "> Select a node to view details .</ div >
1919 </ aside >
2020 </ main >
2121
2222 < script src ="https://unpkg.com/cytoscape@3.4.0/dist/cytoscape.min.js "> </ script >
2323 < script >
2424 const status = document . querySelector ( '.status' ) ;
25+ const sidebarTitle = document . getElementById ( 'sidebar-title' ) ;
2526 const details = document . getElementById ( 'node-details' ) ;
2627
27- function formatNodeData ( node ) {
28+ function escapeHtml ( value ) {
29+ return String ( value || '' )
30+ . replace ( / & / g, '&' )
31+ . replace ( / < / g, '<' )
32+ . replace ( / > / g, '>' )
33+ . replace ( / " / g, '"' )
34+ . replace ( / ' / g, ''' ) ;
35+ }
36+
37+ function renderNodeDetails ( node ) {
2838 const data = node . data ( ) ;
29- return JSON . stringify ( data , null , 2 ) ;
39+ sidebarTitle . textContent = data . label || 'Selected node' ;
40+
41+ const occurrences = Array . isArray ( data . occurrences ) ? data . occurrences : [ ] ;
42+ if ( ! occurrences . length ) {
43+ details . innerHTML = '<p>No occurrences available.</p>' ;
44+ return ;
45+ }
46+
47+ details . innerHTML = occurrences . map ( item => {
48+ const link = escapeHtml ( item . link ) ;
49+ const context = item . context ;
50+ return `
51+ <section>
52+ <p><a href="${ link } " target="_blank" rel="noopener noreferrer">View on GOV.UK</a></p>
53+ <p>${ context } </p>
54+ </section>
55+ ` ;
56+ } ) . join ( '' ) ;
3057 }
3158
3259 async function loadGraph ( ) {
@@ -104,12 +131,13 @@ <h2></h2>
104131 } ) ;
105132
106133 cy . on ( 'tap' , 'node' , ( event ) => {
107- details . textContent = formatNodeData ( event . target ) ;
134+ renderNodeDetails ( event . target ) ;
108135 } ) ;
109136
110137 cy . on ( 'tap' , ( event ) => {
111138 if ( event . target === cy ) {
112- details . textContent = 'No node selected.' ;
139+ sidebarTitle . textContent = 'No node selected' ;
140+ details . innerHTML = '<p>Select a node to view details.</p>' ;
113141 }
114142 } ) ;
115143 } catch ( error ) {
0 commit comments