@@ -329,6 +329,9 @@ <h2>Observation statistics</h2>
329329
330330 infoContainer . innerHTML = content ;
331331 detailsContainer . style . display = 'block' ;
332+
333+ // Update URL with the selected taxon
334+ updateUrlHash ( ) ;
332335}
333336
334337// Search for observations
@@ -346,6 +349,9 @@ <h2>Observation statistics</h2>
346349 return ;
347350 }
348351
352+ // Update URL with current search parameters
353+ updateUrlHash ( ) ;
354+
349355 // Calculate date range
350356 const endDate = new Date ( ) ;
351357 const startDate = new Date ( ) ;
@@ -509,8 +515,92 @@ <h2>Observation statistics</h2>
509515 return date . toLocaleDateString ( ) ;
510516}
511517
518+ // Update URL hash with current state
519+ function updateUrlHash ( ) {
520+ const days = document . getElementById ( 'days-input' ) . value ;
521+
522+ if ( selectedTaxonId && selectedTaxonName ) {
523+ const stateObj = {
524+ taxonId : selectedTaxonId ,
525+ taxonName : selectedTaxonName ,
526+ days : days
527+ } ;
528+
529+ const hashValue = encodeURIComponent ( JSON . stringify ( stateObj ) ) ;
530+
531+ // Use history API to update URL without reloading the page
532+ history . pushState ( stateObj , '' , `#${ hashValue } ` ) ;
533+ }
534+ }
535+
536+ // Load state from URL hash
537+ async function loadStateFromHash ( ) {
538+ const hash = window . location . hash ;
539+
540+ if ( hash && hash . length > 1 ) {
541+ try {
542+ const decodedHash = decodeURIComponent ( hash . slice ( 1 ) ) ;
543+ const stateObj = JSON . parse ( decodedHash ) ;
544+
545+ if ( stateObj && stateObj . taxonId && stateObj . taxonName && stateObj . days ) {
546+ console . log ( 'Loading state from URL hash:' , stateObj ) ;
547+
548+ // Set days input
549+ document . getElementById ( 'days-input' ) . value = stateObj . days ;
550+
551+ // Set the species search input
552+ document . getElementById ( 'species-search' ) . value = stateObj . taxonName ;
553+
554+ // Set the taxon details
555+ selectedTaxonId = stateObj . taxonId ;
556+ selectedTaxonName = stateObj . taxonName ;
557+
558+ const detailsContainer = document . getElementById ( 'taxon-details' ) ;
559+ const infoContainer = document . getElementById ( 'selected-taxon-info' ) ;
560+
561+ infoContainer . innerHTML = `<strong>Selected: ${ stateObj . taxonName } </strong>` ;
562+ detailsContainer . style . display = 'block' ;
563+
564+ // Search for observations
565+ await searchObservations ( ) ;
566+ }
567+ } catch ( error ) {
568+ console . error ( 'Error parsing hash state:' , error ) ;
569+ }
570+ }
571+ }
572+
573+ // Handle browser navigation events
574+ window . addEventListener ( 'popstate' , async ( event ) => {
575+ if ( event . state ) {
576+ // Load state from the history state object
577+ selectedTaxonId = event . state . taxonId ;
578+ selectedTaxonName = event . state . taxonName ;
579+
580+ document . getElementById ( 'days-input' ) . value = event . state . days ;
581+ document . getElementById ( 'species-search' ) . value = event . state . taxonName ;
582+
583+ const detailsContainer = document . getElementById ( 'taxon-details' ) ;
584+ const infoContainer = document . getElementById ( 'selected-taxon-info' ) ;
585+
586+ infoContainer . innerHTML = `<strong>Selected: ${ event . state . taxonName } </strong>` ;
587+ detailsContainer . style . display = 'block' ;
588+
589+ await searchObservations ( ) ;
590+ } else {
591+ // Reset state if no state in history
592+ selectedTaxonId = null ;
593+ selectedTaxonName = null ;
594+ document . getElementById ( 'species-search' ) . value = '' ;
595+ document . getElementById ( 'days-input' ) . value = '30' ;
596+ document . getElementById ( 'taxon-details' ) . style . display = 'none' ;
597+ markers . clearLayers ( ) ;
598+ document . getElementById ( 'stats-panel' ) . style . display = 'none' ;
599+ }
600+ } ) ;
601+
512602// Initialize
513- document . addEventListener ( 'DOMContentLoaded' , ( ) => {
603+ document . addEventListener ( 'DOMContentLoaded' , async ( ) => {
514604 initMap ( ) ;
515605 setupSpeciesSearch ( ) ;
516606
@@ -523,7 +613,32 @@ <h2>Observation statistics</h2>
523613 searchObservations ( ) ;
524614 }
525615 } ) ;
616+
617+ // Load state from URL hash
618+ await loadStateFromHash ( ) ;
526619} ) ;
620+
621+ // Handle direct lookup of a taxon by ID
622+ async function lookupTaxonById ( taxonId ) {
623+ try {
624+ const response = await fetch ( `https://api.inaturalist.org/v1/taxa/${ taxonId } ` ) ;
625+
626+ if ( ! response . ok ) {
627+ throw new Error ( 'Network response was not ok' ) ;
628+ }
629+
630+ const data = await response . json ( ) ;
631+
632+ if ( data . results && data . results . length > 0 ) {
633+ return data . results [ 0 ] ;
634+ }
635+
636+ return null ;
637+ } catch ( error ) {
638+ console . error ( 'Error looking up taxon by ID:' , error ) ;
639+ return null ;
640+ }
641+ }
527642 </ script >
528643</ body >
529644</ html >
0 commit comments