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/hgVai/hgVai.c src/hg/hgVai/hgVai.c
index 31d244dc35a..8a13b4b7af0 100644
--- src/hg/hgVai/hgVai.c
+++ src/hg/hgVai/hgVai.c
@@ -111,71 +111,30 @@
 INLINE void startCollapsibleSection(char *sectionSuffix, char *title, boolean onByDefault)
 // Wrap shared args to jsBeginCollapsibleSectionFontSize
 {
 jsBeginCollapsibleSectionFontSize(cart, "hgva", sectionSuffix, title, onByDefault, "1.1em");
 }
 
 INLINE void startSmallCollapsibleSection(char *sectionSuffix, char *title, boolean onByDefault)
 // Wrap shared args to jsBeginCollapsibleSectionFontSize
 {
 jsBeginCollapsibleSectionFontSize(cart, "hgva", sectionSuffix, title, onByDefault, "0.9em");
 }
 
 #define endCollapsibleSection jsEndCollapsibleSection
 
 
-static struct dyString *onChangeStart()
-/* Start up a javascript onChange command */
-{
-struct dyString *dy = jsOnChangeStart();
-jsTextCarryOver(dy, hgvaRegionType);
-jsTextCarryOver(dy, hgvaRange);
-return dy;
-}
-
-static char *onChangeClade()
-/* Return javascript executed when they change clade. */
-{
-struct dyString *dy = onChangeStart();
-jsDropDownCarryOver(dy, "clade");
-dyStringAppend(dy, " document.hiddenForm.org.value=0;");
-dyStringAppend(dy, " document.hiddenForm.db.value=0;");
-dyStringAppend(dy, " document.hiddenForm." hgvaRange ".value='';");
-return jsOnChangeEnd(&dy);
-}
-
-static char *onChangeOrg()
-/* Return javascript executed when they change organism. */
-{
-struct dyString *dy = onChangeStart();
-jsDropDownCarryOver(dy, "clade");
-jsDropDownCarryOver(dy, "org");
-dyStringAppend(dy, " document.hiddenForm.db.value=0;");
-dyStringAppend(dy, " document.hiddenForm." hgvaRange ".value='';");
-return jsOnChangeEnd(&dy);
-}
-
-static char *onChangeDb()
-/* Return javascript executed when they change database. */
-{
-struct dyString *dy = onChangeStart();
-jsDropDownCarryOver(dy, "clade");
-jsDropDownCarryOver(dy, "db");
-dyStringAppend(dy, " document.hiddenForm." hgvaRange ".value='';");
-return jsOnChangeEnd(&dy);
-}
-
 INLINE void printOption(char *val, char *selectedVal, char *label)
 /* For rolling our own select without having to build conditional arrays/lists. */
 {
 printf("<OPTION VALUE='%s'%s>%s\n", val, (sameString(selectedVal, val) ? " SELECTED" : ""), label);
 }
 
 void printRegionListHtml(char *db)
 /* Make a dropdown choice of region type, with position input box that appears if needed.
  * Unlike hgTables, don't bother with ENCODE pilot regions -- unless someone misses it.
  * Return the selected region type. */
 {
 printf("<SELECT ID='"hgvaRegionType"' NAME='"hgvaRegionType"'>\n");
 jsOnEventById("change", hgvaRegionType, "hgva.changeRegion();");
 printOption(hgvaRegionTypeGenome, regionType, "genome");
 printOption(hgvaRegionTypeRange, regionType, "position or search term");
@@ -211,69 +170,72 @@
 hOnClickButton("prtCtHub_CtBut", "document.customTrackForm.submit(); return false;",
 	       hasCustomTracks ? CT_MANAGE_BUTTON_LABEL : CT_ADD_BUTTON_LABEL);
 printf(" ");
 if (hubConnectTableExists())
     hOnClickButton("prtCtHub_TrkHub", "document.trackHubForm.submit(); return false;", "track hubs");
 nbSpaces(3);
 printf("To reset <B>all</B> user cart settings (including custom tracks), \n"
        "<A HREF=\"cartReset?destination=%s\">click here</A>.\n",
        cgiScriptName());
 puts("</div>");
 }
 
 void hgGatewayCladeGenomeDb()
 /* Make a row of labels and row of buttons like hgGateway, but not using tables. */
 {
-boolean gotClade = hGotClade();
-if (gotClade)
-    {
-    topLabelSpansStart("clade");
-    printCladeListHtml(genome, "change", onChangeClade());
-    topLabelSpansEnd();
-    }
-topLabelSpansStart("genome");
-if (gotClade)
-    printGenomeListForCladeHtml(database, "change", onChangeOrg());
-else
-    printGenomeListHtml(database, "change", onChangeOrg());
-topLabelSpansEnd();
-topLabelSpansStart("assembly");
-printAssemblyListHtml(database, "change", onChangeDb());
-topLabelSpansEnd();
+jsIncludeAutoCompleteLibs();
+char *searchBarId = "genomeSearch";
+printf("<div class='searchCell'>\n");
+printGenomeSearchBar(searchBarId, "Search any species, genome or assembly name", NULL, TRUE, "Change selected genome:", NULL);
+jsInlineF(
+    "setupGenomeSearchBar({\n"
+    "    inputId: '%s',\n"
+    "    onSelect: function(item) {\n"
+    "        document.hiddenForm.db.value = item.genome;\n"
+    "        document.hiddenForm.hgva_regionType.value = document.getElementById('hgva_regionType').value;\n"
+    "        document.hiddenForm.submit();\n"
+    "    }\n"
+    "});\n"
+    , searchBarId
+);
+printf("<div class='searchCell'>\n");
+char *dbLabel = getCurrentGenomeLabel(database);
+printf("Current Genome: <span id='genomeLabel'>%s</span>\n", dbLabel);
+printf("</div>\n");
 puts("<BR>");
 topLabelSpansStart("region to annotate");
 printRegionListHtml(database);
 topLabelSpansEnd();
 topLabelSpansStart("");
 // Yet another span, for hiding/showing position input and lookup button:
 printf("<span id='"hgvaPositionContainer"'%s>\n",
        differentString(regionType, hgvaRegionTypeRange) ? " style='display: none;'" : "");
 puts(makePositionInput());
 printf("</span>\n");
 topLabelSpansEnd();
 puts("<BR>");
 }
 
 void printAssemblySection()
 /* Print assembly-selection stuff.
  * Redrawing the whole page when the assembly changes seems fine to me. */
 {
 //#*** ---------- More copied verbatim, from hgTables/mainPage.c: -----------
 /* Hidden form - for benefit of javascript. */
     {
     static char *saveVars[] = {
-      "clade", "org", "db", hgvaRange, hgvaRegionType };
+      "db", hgvaRange, hgvaRegionType };
     jsCreateHiddenForm(cart, cgiScriptName(), saveVars, ArraySize(saveVars));
     }
 
 /* Hidden form for jumping to custom tracks CGI. */
 printf("<FORM ACTION='%s' NAME='customTrackForm' ID='customTrackForm'>", hgCustomName());
 cartSaveSession(cart);
 printf("</FORM>\n");
 
 /* Hidden form for jumping to track hub manager CGI. */
 printf("<FORM ACTION='%s' NAME='trackHubForm'>", hgHubConnectName());
 //#*** well, almost verbatim... lib version should use cgiScriptName.
 cartSaveSession(cart);
 printf("</FORM>\n");
 
 printf("<FORM ACTION=\"%s\" NAME=\"mainForm\" ID=\"mainForm\" METHOD=%s>\n",