@@ -92,18 +92,45 @@ function addGlobalHazardTiles(map, apiBaseUrl = "http://localhost:5000") {
9292 } ,
9393 } ) ;
9494
95+ // Global variable to track current popup for ESC key functionality
96+ let currentPopup = null ;
97+
98+ // Add ESC key event listener for closing popups
99+ document . addEventListener ( "keydown" , function ( event ) {
100+ if ( event . key === "Escape" && currentPopup ) {
101+ currentPopup . remove ( ) ;
102+ currentPopup = null ;
103+ }
104+ } ) ;
105+
95106 // Add click interaction for Global Hazard Points features
96107 map . on ( "click" , "hazard-pt" , ( e ) => {
108+ // Close existing popup if any
109+ if ( currentPopup ) {
110+ currentPopup . remove ( ) ;
111+ currentPopup = null ;
112+ }
113+
97114 const properties = e . features [ 0 ] . properties ;
98115 const featureId = properties . id || Date . now ( ) ;
99116
100- // Build table rows for feature properties
101- let rows = "" ;
102- for ( const [ key , value ] of Object . entries ( properties ) ) {
103- if ( key !== "id" && key !== "fid" ) {
104- rows += `<tr><td>${ key } </td><td>${ value } </td></tr>` ;
105- }
106- }
117+ // Build limited properties table (first 7 items)
118+ const propertyEntries = Object . entries ( properties ) . filter (
119+ ( [ key ] ) => key !== "id" && key !== "fid"
120+ ) ;
121+ const visibleProperties = propertyEntries . slice ( 0 , 7 ) ;
122+ const hiddenProperties = propertyEntries . slice ( 7 ) ;
123+
124+ let visibleRows = "" ;
125+ let hiddenRows = "" ;
126+
127+ visibleProperties . forEach ( ( [ key , value ] ) => {
128+ visibleRows += `<tr><td>${ key } </td><td>${ value } </td></tr>` ;
129+ } ) ;
130+
131+ hiddenProperties . forEach ( ( [ key , value ] ) => {
132+ hiddenRows += `<tr><td>${ key } </td><td>${ value } </td></tr>` ;
133+ } ) ;
107134
108135 const canvasId = `rate-chart-${ featureId } ` ;
109136 const downloadId = `download-${ featureId } ` ;
@@ -114,15 +141,21 @@ function addGlobalHazardTiles(map, apiBaseUrl = "http://localhost:5000") {
114141 <canvas id="${ canvasId } " width="400" height="160"></canvas>
115142 <button class="download-btn" id="${ downloadId } ">Download CSV</button>
116143 <details class="properties-details">
117- <summary>Properties</summary>
144+ <summary>Properties ( ${ propertyEntries . length } total) </summary>
118145 <div class="properties-content">
119- <table class="popup-table">${ rows } </table>
146+ <div class="properties-scroll-container">
147+ <table class="popup-table">
148+ ${ visibleRows }
149+ ${ hiddenRows }
150+ </table>
151+ </div>
120152 </div>
121153 </details>
154+ <div class="popup-hint">💡 Press <kbd>ESC</kbd> to close this popup</div>
122155 </div>` ;
123156
124157 // Create popup with improved configuration to prevent jumping
125- const popup = new maplibregl . Popup ( {
158+ currentPopup = new maplibregl . Popup ( {
126159 maxWidth : "480px" ,
127160 className : "chart-popup" ,
128161 closeOnClick : false ,
@@ -134,22 +167,27 @@ function addGlobalHazardTiles(map, apiBaseUrl = "http://localhost:5000") {
134167 . setHTML ( html )
135168 . addTo ( map ) ;
136169
170+ // Handle popup close event to reset currentPopup
171+ currentPopup . on ( "close" , ( ) => {
172+ currentPopup = null ;
173+ } ) ;
174+
137175 // Adjust popup position if it goes off screen
138176 setTimeout ( ( ) => {
139- const popupElement = popup . getElement ( ) ;
177+ const popupElement = currentPopup . getElement ( ) ;
140178 if ( popupElement ) {
141179 const rect = popupElement . getBoundingClientRect ( ) ;
142180 const mapContainer = map . getContainer ( ) . getBoundingClientRect ( ) ;
143181
144182 // Check if popup extends beyond screen boundaries
145183 if ( rect . right > mapContainer . right ) {
146- popup . setOffset ( [ - rect . width / 2 , - 10 ] ) ;
184+ currentPopup . setOffset ( [ - rect . width / 2 , - 10 ] ) ;
147185 }
148186 if ( rect . left < mapContainer . left ) {
149- popup . setOffset ( [ rect . width / 2 , - 10 ] ) ;
187+ currentPopup . setOffset ( [ rect . width / 2 , - 10 ] ) ;
150188 }
151189 if ( rect . top < mapContainer . top ) {
152- popup . setOffset ( [ 0 , 10 ] ) ;
190+ currentPopup . setOffset ( [ 0 , 10 ] ) ;
153191 }
154192 }
155193 } , 50 ) ;
@@ -292,30 +330,36 @@ function addGlobalHazardTiles(map, apiBaseUrl = "http://localhost:5000") {
292330
293331 // Handle properties details expansion to prevent popup jumping
294332 setTimeout ( ( ) => {
295- const detailsElement = popup
333+ const detailsElement = currentPopup
296334 . getElement ( )
297335 . querySelector ( ".properties-details" ) ;
298336 if ( detailsElement ) {
299337 detailsElement . addEventListener ( "toggle" , ( e ) => {
300338 // Small delay to allow content to render
301339 setTimeout ( ( ) => {
302- const popupElement = popup . getElement ( ) ;
340+ const popupElement = currentPopup . getElement ( ) ;
303341 const rect = popupElement . getBoundingClientRect ( ) ;
304342 const mapContainer = map . getContainer ( ) . getBoundingClientRect ( ) ;
305343
306344 // Adjust popup position if it goes beyond screen after expansion
307345 if ( rect . bottom > mapContainer . bottom ) {
308346 // Move popup up if it goes below screen
309347 const newOffset = [ 0 , - ( rect . height + 20 ) ] ;
310- popup . setOffset ( newOffset ) ;
348+ currentPopup . setOffset ( newOffset ) ;
311349 }
312350
313351 // Ensure popup doesn't go off the sides
314352 if ( rect . right > mapContainer . right ) {
315- popup . setOffset ( [ - rect . width / 2 , popup . getOffset ( ) [ 1 ] ] ) ;
353+ currentPopup . setOffset ( [
354+ - rect . width / 2 ,
355+ currentPopup . getOffset ( ) [ 1 ] ,
356+ ] ) ;
316357 }
317358 if ( rect . left < mapContainer . left ) {
318- popup . setOffset ( [ rect . width / 2 , popup . getOffset ( ) [ 1 ] ] ) ;
359+ currentPopup . setOffset ( [
360+ rect . width / 2 ,
361+ currentPopup . getOffset ( ) [ 1 ] ,
362+ ] ) ;
319363 }
320364 } , 50 ) ;
321365 } ) ;
0 commit comments