7e32381bc2152e0bdf4e5be2f46fe033e80cb5d5
jrobinso
  Mon Sep 15 17:41:54 2025 -0700
(1) Broadcast a "filePickerReady" message on filePicker.html mode.  (2) Make special input mode optional with a config parameter.

diff --git src/hg/htdocs/admin/filePicker.html src/hg/htdocs/admin/filePicker.html
index 302ab7a196b..7ea150cb67e 100644
--- src/hg/htdocs/admin/filePicker.html
+++ src/hg/htdocs/admin/filePicker.html
@@ -84,70 +84,77 @@
         <input type="url" id="urlInput">
     </div>
     <div class="input-row">
         <label for="indexURLInput">Index URL</label>
         <input type="url" id="indexURLInput">
     </div>
     <p>
         <button id="urlButton">Load</button>
     </p>
 </section>
 
 
 <script>
     document.addEventListener('DOMContentLoaded', () => {
         const channel = new BroadcastChannel('igv_file_channel')
+        channel.postMessage({type: 'filePickerReady'})
         const fileCache = new Map()
         const restoreCache = new Map()
 
         document.getElementById('fileInput').addEventListener('change', function (event) {
             const files = []
             for (let file of event.target.files) {
                 const id = `${file.name}_${file.size}`
                 files.push({id, file}) //value)
                 fileCache.set(id, file)
                 restoreCache.delete(id)
                 refreshFileList()
             }
             event.target.value = ""
 
             channel.postMessage({type: 'selectedFiles', files: files})
         })
 
         document.getElementById("urlButton").addEventListener('click', event => {
             const url = document.getElementById("urlInput").value
             if (url) {
                 let indexURL = document.getElementById("indexURLInput").value
                 if (!indexURL) {
                     if (url.endsWith(".bam")) {
                         indexURL = url + ".bai"
                     } else if (url.endsWith(".cram")) {
                         indexURL = url + ".crai"
                     } else if (url.endsWith(".vcf.gz")) {
                         indexURL = url + ".tbi"
                     }
                 }
-                channel.postMessage({type: 'loadURL', config: {url, indexURL}})
+                channel.postMessage({type: 'loadURL', config: {id: url, url, indexURL}})
             }
         })
 
         // Respond to messages from the browser page
         channel.onmessage = function (event) {
             const {id, type} = event.data
             if (type === 'getFile') {
                 const selectedFile = fileCache.get(id)
+
+                if(selectedFile) {
                 channel.postMessage({type: 'file', data: selectedFile})   // TODO -- what if selectedFile is undefined?  Handle here or in browser?
+                } else {
+                    // Don't respond if we don't have the file.  Its possible multiple file pickers are open.
+                    console.info(`No file found for id: ${id}`)
+                }
             } else if (type === 'removeFile') {
                 fileCache.delete(id)
                 refreshFileList()
             } else if (type === 'restoreFiles') {
                 const failed = event.data.files
                 for (const f of failed) {
                     restoreCache.set(f.id, f.name)
                 }
                 refreshFileList()
             } else if (type === 'removedTrack') {
                 // TODO -- might want to remove from restoreCache too
                 const config = event.data.config
                 if (config.url && config.url.id) {
                     fileCache.delete(config.url.id)
                     restoreCache.delete(config.url.id)