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/hgCustom/hgCustom.c src/hg/hgCustom/hgCustom.c index 5a3b9e78654..6503c2fc046 100644 --- src/hg/hgCustom/hgCustom.c +++ src/hg/hgCustom/hgCustom.c @@ -149,98 +149,89 @@ " If you do not have web-accessible data storage available, please see the\n" " <A TARGET=_BLANK HREF='../goldenPath/help/hgTrackHubHelp.html#Hosting'>Hosting</A> section of the Track Hub Help documentation.\n<br><br></li>" " </ul>\n" " Please note a much more efficient way to load data is to use\n" " <A TARGET=_BLANK HREF='../goldenPath/help/hgTrackHubHelp.html'>Track Hubs</A>, which are loaded\n" " from the <A TARGET=_BLANK HREF='hgHubConnect'>Track Hubs Portal</A> found in the menu under My Data.\n" ); } void addCustomForm(struct customTrack *ct, char *err, boolean warnOnly) /* display UI for adding custom tracks by URL or pasting data */ { char *dataUrl = NULL; char buf[1024]; -boolean gotClade = FALSE; boolean isUpdateForm = FALSE; if (ct) { isUpdateForm = TRUE; dataUrl = ctDataUrl(ct); } -else - /* add form needs clade for assembly menu */ - gotClade = hGotClade(); jsIncludeFile("jquery.js", NULL); jsIncludeFile("hgCustom.js", NULL); jsIncludeFile("utils.js", NULL); jsIncludeFile("ajax.js", NULL); if (cfgOptionBooleanDefault("showTutorial", TRUE)) { jsIncludeFile("shepherd.min.js", NULL); webIncludeResourceFile("shepherd.css"); jsIncludeFile("jquery-ui.js", NULL); webIncludeResourceFile("jquery-ui.css"); jsIncludeFile("tutorialPopup.js", NULL); jsIncludeFile("customTrackTutorial.js", NULL); if (sameOk(cgiOptionalString("startCustomTutorial"), "true")) { jsInline("var startCustomTutorialOnLoad = true;"); } } /* main form */ printf("<FORM ACTION=\"%s\" METHOD=\"%s\" " " ENCTYPE=\"multipart/form-data\" NAME=\"mainForm\" id='mainForm'>\n", hgCustomName(), cartUsualString(cart, "formMethod", "POST")); jsOnEventById("submit", "mainForm", "$('input[name=Submit]').attr('disabled', 'disabled');"); cartSaveSession(cart); if (!isUpdateForm) { - /* Print clade, genome and assembly */ - /* NOTE: this uses an additional, hidden form (orgForm), below */ - char *onChangeDb = "document.orgForm.db.value = document.mainForm.db.options[document.mainForm.db.selectedIndex].value; document.orgForm.submit();"; - char *onChangeOrg = "document.orgForm.org.value = document.mainForm.org.options[document.mainForm.org.selectedIndex].value; document.orgForm.db.value = 0; document.orgForm.submit();"; - char *onChangeClade = "document.orgForm.clade.value = document.mainForm.clade.options[document.mainForm.clade.selectedIndex].value; document.orgForm.org.value = 0; document.orgForm.db.value = 0; document.orgForm.submit();"; - + /* Print genome search bar and selected genome label */ puts("<TABLE id=\"genome-selection-table\" BORDER=0>\n"); - if (gotClade) - { - puts("<TR><TD>Clade\n"); - printCladeListHtml(hOrganism(database), "change", onChangeClade); - puts(" "); - puts("Genome\n"); - printGenomeListForCladeHtml(database, "change", onChangeOrg); - } - else - { - puts("<TR><TD>genome\n"); - printGenomeListHtml(database, "change", onChangeOrg); - } - puts(" "); - puts("Assembly\n"); - printAssemblyListHtml(database, "change", onChangeDb); - char *description = hFreezeFromDb(database); - if ((description != NULL) && ! stringIn(database, description)) - { - puts(" "); - printf("[%s]", trackHubSkipHubName(database)); - } - puts("</TD></TR></TABLE>\n"); + printf("<tr>\n"); + printf("<td class='searchCell' align=center>\n"); + // hgCustom requires this <input> be created to go along with form submission, we + // will change it when a genome is selected in the search bar + printf("<input name='db' value='%s' type='hidden'></input>\n", database); + jsIncludeAutoCompleteLibs(); + char *searchBarId = "genomeSearch"; + 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.mainForm.db.value = item.genome;\n" + " }\n" + "});\n" + , searchBarId + ); + printf("</td>\n"); + printf("<td class='searchCell' align=center>\n"); + char *dbLabel = getCurrentGenomeLabel(database); + printf("Current Genome: <span id='genomeLabel'>%s</span>\n", dbLabel); + printf("</td>\n"); + puts("</TR></TABLE>\n"); } /* intro text */ puts("<P>"); if (isUpdateForm) puts("Update your custom track configuration, data, and/or documentation."); else puts("Display your own data as custom annotation tracks in the browser."); addIntro(); puts("<P>"); /* row for error message */ if (isNotEmpty(err)) { printf("<P><B> <span style='color:%s; font-style:italic;'>" @@ -467,43 +458,30 @@ if (isUpdateForm) { /* hidden variables to identify track */ cgiMakeHiddenVar(hgCtUpdatedTable, ct->tdb->track); char buf[512]; char *shortLabel = htmlEncode(ct->tdb->shortLabel); char *longLabel = htmlEncode(ct->tdb->longLabel); safef(buf, sizeof buf, "track name='%s' description='%s'", shortLabel, longLabel); char *trackLine = htmlEncode(ctOrigTrackLine(ct)); cgiMakeHiddenVar(hgCtUpdatedTrack, trackLine ? trackLine : buf); freeMem(trackLine); freeMem(shortLabel); freeMem(longLabel); } -else - { - /* hidden form to handle clade/genome/assembly dropdown. - * This is at end of page for layout reasons (preserve vertical space) */ - puts("</FORM>"); - printf("<FORM STYLE=\"margin-bottom:0;\" ACTION=\"%s\" METHOD=\"GET\" NAME=\"orgForm\">", hgCustomName()); - cartSaveSession(cart); - if (gotClade) - printf("<INPUT TYPE=\"HIDDEN\" NAME=\"clade\" VALUE=\"\">\n"); - printf("<INPUT TYPE=\"HIDDEN\" NAME=\"org\" VALUE=\"%s\">\n", organism); - printf("<INPUT TYPE=\"HIDDEN\" NAME=\"db\" VALUE=\"%s\">\n", database); - printf("<INPUT TYPE=\"HIDDEN\" NAME=\"hgct_do_add\" VALUE=\"1\">\n"); - } puts("</FORM>"); cgiDown(0.9); } void tableHeaderFieldStart(int columns) { /* print table column header with white text on black background */ printf("<TD COLSPAN=%d ALIGN='CENTER' BGCOLOR='#536ED3'>", columns); } void tableHeaderField(char *label, char *description) { /* print table column header with white text on black background */ puts("<TD ALIGN='CENTER' BGCOLOR='#536ED3' "); if (description)