16eee40c920d259c10ee345472708d0cc0cc3393
chmalee
  Tue Mar 3 11:25:23 2026 -0800
Adds an hg.conf defined 'popular' species list to the new search bar as a 'default' list of results upon focus of the search bar. Combines with 'recents' list. Add a chevron next to the search bar so users know the autocomplete has some default options, refs #36232

diff --git src/hg/hgSearch/hgSearch.c src/hg/hgSearch/hgSearch.c
index b14ffde25de..f3d0cb81ec2 100644
--- src/hg/hgSearch/hgSearch.c
+++ src/hg/hgSearch/hgSearch.c
@@ -490,40 +490,70 @@
     }
 jsonElementSaveCategoriesToCart(db,jel);
 }
 
 void doCartJson()
 /* Register functions that return JSON to client */
 {
 struct cartJson *cj = cartJsonNew(cart);
 cartJsonRegisterHandler(cj, "getSearchResults", getSearchResults);
 cartJsonRegisterHandler(cj, "getUiState", getUiState);
 cartJsonRegisterHandler(cj, "saveCategoriesToCart", doSaveCategoriesToCart);
 cartJsonRegisterHandler(cj, "getChromName", getChromName);
 cartJsonExecute(cj);
 }
 
+static void printPopularDataJson()
+/* Emit a <script type='application/json' id='genomeSearchPopularData'> block
+ * with the same format as printGenomeSearchBar() in web.c, so that
+ * setupGenomeSearchBar() in utils.js can show Popular items on empty input. */
+{
+char *popularStr = cfgOptionDefault("browser.popularGenomes",
+    "hg38,hg19,mm39,mm10,rn7,danRer11,dm6,ce11,sacCer3");
+struct slName *dbNames = slNameListFromComma(popularStr);
+struct dyString *json = dyStringNew(512);
+dyStringAppendC(json, '[');
+boolean first = TRUE;
+struct slName *dbIter;
+for (dbIter = dbNames; dbIter != NULL; dbIter = dbIter->next)
+    {
+    struct dbDb *info = hDbDb(dbIter->name);
+    if (info == NULL || !info->active)
+        continue;
+    if (!first)
+        dyStringAppendC(json, ',');
+    first = FALSE;
+    dyStringPrintf(json, "{\"db\":\"%s\",\"label\":\"%s - %s (%s)\",\"commonName\":\"%s\"}",
+        info->name, info->organism, info->description, info->name, info->organism);
+    }
+dyStringAppendC(json, ']');
+printf("<script type='application/json' id='genomeSearchPopularData'>%s</script>\n", dyStringContents(json));
+dyStringFree(&json);
+slFreeList(&dbNames);
+}
+
 void doMainPage()
 /* Print the basic HTML page and include any necessary Javascript. AJAX calls
  * will fill out the page later */
 {
 char *database = NULL;
 char *genome = NULL;
 getDbAndGenome(cart, &database, &genome, oldVars);
 webStartGbNoBanner(cart, database, "Search Disambiguation");
 printMainPageIncludes();
 jsInlineF("var hgsid='%s';\n", cartSessionId(cart));
+printPopularDataJson();
 struct jsonElement *cartJson = newJsonObject(hashNew(0));
 jsonObjectAdd(cartJson, "db", newJsonString(database));
 jsonObjectAdd(cartJson, "genomes", getGenomes());
 struct dyString *cartJsonDy = dyStringNew(0);
 jsonDyStringPrint(cartJsonDy, cartJson, "cartJson", -1);
 jsInlineF("%s;\n", dyStringCannibalize(&cartJsonDy));
 // Call our init function to fill out the page
 jsInline("hgSearch.init();\n");
 webEndGb();
 }
 
 void doSearchOnly()
 /* Send back search results along with whatever we need to make the UI */
 {
 cartJsonPushErrHandlers();
@@ -603,30 +633,31 @@
     puts("</HEAD>\n</HTML>");
     }
 else
     {
     dyStringPrintf(cj->jw->dy, ", \"db\": '%s'", db);
     dyStringPrintf(cj->jw->dy, ", \"categs\": ");
     jsonDyStringPrint(cj->jw->dy, categsJsonElement, NULL,-1);
     dyStringPrintf(cj->jw->dy, ", \"trackGroups\": ");
     jsonDyStringPrint(cj->jw->dy, makeTrackGroupsJson(db), NULL, -1);
     dyStringPrintf(cj->jw->dy, ", \"genomes\": ");
     jsonDyStringPrint(cj->jw->dy, getGenomes(), NULL, -1);
 
     // Now we need to actually spit out the page + json
     webStartGbNoBanner(cart, db, "Search Disambiguation");
     printMainPageIncludes();
+    printPopularDataJson();
     cartJsonPrintWarnings(cj->jw);
     jsInlineF("var hgsid='%s';\n", cartSessionId(cart));
     jsInline("var cartJson = {");
     jsInline(cj->jw->dy->string);
     jsInline("};\n");
     jsInline("hgSearch.init();\n");
     webEndGb();
     }
 cartJsonPopErrHandlers();
 }
 /* End do commands */
 
 void doMiddle(struct cart *theCart)
 /* Set up globals and make web page */
 {