47ea57080b515e5dad5f658c58feb8944a7e7d61 chmalee Thu Jan 29 15:30:26 2026 -0800 Replace clade/assembly dropdowns with a search bar on most CGIs. Add a recents list to hgGateway and to the species bar and to the 'Genomes' dropdown menu. Track recently selected species in localStorage. Add toGenome and fromGenome arguemnts to hubApi/liftOver in order to find appropriate liftover assemblies, refs #36232 diff --git src/hg/js/hgSearch.js src/hg/js/hgSearch.js index c013ff5b1a8..7073b0325be 100644 --- src/hg/js/hgSearch.js +++ src/hg/js/hgSearch.js @@ -619,78 +619,92 @@ $('#'+idAttr.value+"_" +categoryCount+"_showMoreButton").click(showMoreResults); $('#'+idAttr.value + "_" + categoryCount + "_showMoreLink").click(showMoreResults); categoryCount += 1; }); } else if (uiState && typeof uiState.search !== "undefined") { // No results from match var msg = "<p>No results</p>"; parentDiv.empty(); parentDiv.html(msg); clearOldFacetCounts(); } else { parentDiv.empty(); } } - function fillOutAssemblies(e) { - organism = $("#speciesSelect")[0].value; - select = $("#dbSelect"); - select.empty(); - _.each(_.sortBy(uiState.genomes[organism], ['orderKey']), function(assembly) { - newOpt = document.createElement("option"); - newOpt.value = assembly.name; - newOpt.label = trackHubSkipHubName(assembly.organism) + " " + assembly.description; - if (assembly.name == db) { - newOpt.selected = true; - } - $("#dbSelect").append(newOpt); - }); - // if we are getting here from a change event on the species dropdown - // and are switching to the default assembly for a species, we can - // automatically send a search for this organism+assembly - if (typeof e !== "undefined") { - switchAssemblies($("#dbSelect")[0].value); - } - } - - function buildSpeciesDropdown() { - // Process the species select dropdowns - _.each(uiState.genomes, function(genome) { - newOpt = document.createElement("option"); - newOpt.value = genome[0].organism; - newOpt.label = trackHubSkipHubName(genome[0].organism); - if (genome.some(function(assembly) { - if (assembly.isCurated) { - if (assembly.name === trackHubSkipHubName(db)) { - return true; + function onGenomeSelect(item) { + // Called when user selects a genome from autocomplete + // item.genome is the db name from hubApi/findGenome + // Just update the label and store the selection - don't reload the page + if (item.disabled || !item.genome) return; + db = item.genome; + $("#currentGenome").text(item.commonName + ' - ' + item.genome); + $("#genomeSearchInput").val(''); } - } else { - if (assembly.name === db) { - return true; + + function onSearchError(jqXHR, textStatus, errorThrown, term) { + return [{label: 'No genomes found', value: '', genome: '', disabled: true}]; } + + function initGenomeAutocomplete() { + // Initialize the genome search autocomplete using the standard function from utils.js + initSpeciesAutoCompleteDropdown('genomeSearchInput', onGenomeSelect, null, null, null, onSearchError); + + // Add click handler for the Change Genome button to trigger autocomplete search + $("#genomeSearchButton").click(function(e) { + e.preventDefault(); + $("#genomeSearchInput").autocomplete("search", $("#genomeSearchInput").val()); + }); } - })) { - newOpt.selected = true; + + function updateCurrentGenomeLabel() { + // Update the label showing current genome + var genomeInfo = null; + // Find the current db in the genomes data + _.each(uiState.genomes, function(genomeList) { + _.each(genomeList, function(assembly) { + if (assembly.name === db || + (assembly.isCurated && assembly.name === trackHubSkipHubName(db))) { + genomeInfo = assembly; } - $("#speciesSelect").append(newOpt); }); + }); + if (genomeInfo) { + $("#currentGenome").text(genomeInfo.organism + ' - ' + genomeInfo.description + ' (' + db + ')'); + } else { + $("#currentGenome").text(db); + } } function changeSearchResultsLabel() { - // change the title to indicate what assembly was search: + // change the title to indicate what assembly was searched: $("#dbPlaceholder").empty(); - $("#dbPlaceholder").append("on " + db + " (" + $("#dbSelect")[0].selectedOptions[0].label+ ")"); + var genomeInfo = null; + // Find the current db in the genomes data + _.each(uiState.genomes, function(genomeList) { + _.each(genomeList, function(assembly) { + if (assembly.name === db || + (assembly.isCurated && assembly.name === trackHubSkipHubName(db))) { + genomeInfo = assembly; + } + }); + }); + if (genomeInfo) { + $("#dbPlaceholder").append("on " + db + " (" + genomeInfo.organism + " " + genomeInfo.description + ")"); + } else { + $("#dbPlaceholder").append("on " + db); + } } function checkJsonData(jsonData, callerName) { // Return true if jsonData isn't empty and doesn't contain an error; // otherwise complain on behalf of caller. if (! jsonData) { alert(callerName + ': empty response from server'); } else if (jsonData.error && !jsonData.error.startsWith("Sorry, couldn't locate")) { console.error(jsonData.error); alert(callerName + ': error from server: ' + jsonData.error); } else if (jsonData.warning) { alert("Warning: " + jsonData.warning); return true; } else { if (debugCartJson) { @@ -711,32 +725,31 @@ return; } if (typeof jsonData.positionMatches !== "undefined") { // clear the old resultHash uiState.resultHash = {}; _.each(uiState.positionMatches, function(match) { uiState.resultHash[match.name] = match; }); } else { // no results for this search uiState.resultHash = {}; uiState.positionMatches = []; } updateFilters(uiState); updateSearchResults(uiState); - buildSpeciesDropdown(); - fillOutAssemblies(); + updateCurrentGenomeLabel(); urlVars = {"db": db, "search": uiState.search, "showSearchResults": ""}; // changing the url allows the history to be associated to a specific url var urlParts = changeUrl(urlVars); $("#searchCategories").jstree(true).refresh(false,true); saveLinkClicks(); if (doSaveHistory) saveHistory(uiState, urlParts); changeSearchResultsLabel(); } function handleRefreshState(jsonData) { if (checkJsonData(jsonData, 'handleRefreshState')) { updateStateAndPage(jsonData, true); } $("#spinner").remove(); @@ -955,38 +968,32 @@ $("#searchCategories").on('check_node.jstree uncheck_node.jstree', function(e, data) { if ($("#searchResults")[0].children.length > 0) { showOrHideResults(e,data.node); } }); // Reattach event handlers as necessary: saveLinkClicks(); }); saveHistory(cartJson, urlParts, true); } else { // no cartJson object means we are coming to the page for the first time: cart.send({ getUiState: {db: db} }, handleRefreshState); cart.flush(); } - buildSpeciesDropdown(); // make the list of available organisms - fillOutAssemblies(); // call once to get the initial state - $("#speciesSelect").change(fillOutAssemblies); - $("#dbSelect").change(function(e) { - e.preventDefault(); - db = e.currentTarget.value; - switchAssemblies(db); - }); + initGenomeAutocomplete(); // initialize the genome search autocomplete + updateCurrentGenomeLabel(); // show the current genome changeSearchResultsLabel(); } return { init: init, updateSearchResults: updateSearchResults, updateFilters: updateFilters, updateStateAndPage: updateStateAndPage }; }()); $(document).ready(function() { $('#searchBarSearchString').bind('keypress', function(e) { // binds listener to search button if (e.which === 13) { // listens for return key e.preventDefault(); // prevents return from also submitting whole form