732a3a2888f039e163586d38688f1372aab04c78
galt
  Thu May 11 21:10:06 2023 -0700
Fix html problems with hgHubConnect, fixes the alignment of columns to headers and also improves the alignment of the search details section. fixes #31250

diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c
index 28ff217..d488df8 100644
--- src/hg/hgHubConnect/hgHubConnect.c
+++ src/hg/hgHubConnect/hgHubConnect.c
@@ -555,39 +555,38 @@
 puts("<BR><BR>\n");
 printf("When exploring the detailed search results for a hub, you may right-click "
         "on an assembly or track line to open it in a new window.\n");
 puts("<BR><BR>\n");
 }
 
 
 void printHubListHeader()
 /* Write out the header for a list of hubs in its own table */
 {
 puts("<table id=\"publicHubsTable\" class=\"hubList\"> "
         "<thead><tr> "
             "<th>Display</th> "
             "<th>Hub Name</th> "
             "<th>Description</th> "
-            //"<th>Assemblies</th> "
             "<th>Assemblies<span class='assemblyClickNote'>Click to connect and browse directly</span></th> "
-        "</tr></thead><tbody><tr><td>");
+        "</tr></thead><tbody>");
 }
 
 void printHubListFooter()
 /* Write out the header for a list of hubs in its own table */
 {
-puts("</td></tr></tbody></table>");
+puts("</tbody></table>");
 }
 
 void outputPublicTableRow(struct hubEntry *hubInfo, int count)
 /* Prints out a table row with basic information about a hub and a button
  * to connect to that hub */
 {
 int id = hubInfo->id;
 char jsId[256];
 struct slName *dbListNames = slNameListFromComma(hubInfo->dbList);
 printf("<tr>\n");
 if (id != 0)
     {
     ourCellStart();
     char hubName[32];
     safef(hubName, sizeof(hubName), "%s%u", hgHubConnectHubVarPrefix, id);
@@ -1097,47 +1096,46 @@
 dyStringPrintf(dy, "%s", genomeDy->string);
 jsInline(dy->string);
 dyStringClear(dy);
 }
 
 static void printOutputForHub(struct hubEntry *hubInfo, struct hubSearchText *hubSearchResult, int count)
 /* Given a hub's info and a structure listing the search hits within the hub, first print
  * a basic line of hub information with a "connect" button.  Then, if the search results
  * are non-NULL, write out information about the genomes and tracks from the search hits that
  * match the db filter.
  * If there are no search results to print, the basic hub lines are combined into a single HTML table
  * that is defined outside this function.
  * Otherwise, each hub line is printed in its own table followed by a <ul> containing details
  * about the search results. */
 {
-if (hubSearchResult != NULL)
-    printf("<table class='hubList'><tbody>\n");
 outputPublicTableRow(hubInfo, count);
 if (hubSearchResult != NULL)
     {
-    printf("</tbody></table>\n");
+    printf("<tr><td colspan=4 style='text-align:left;'>\n");
     struct trackHub *hub = fetchTrackHub(hubInfo);
     if (hub != NULL)
         {
         struct hubOutputStructure *hubOut = buildHubSearchOutputStructure(hub, hubSearchResult);
         if (dyStringIsEmpty(hubOut->descriptionMatch) && (hubOut->genomes == NULL))
             return; // no detailed search results; hit must have been to hub short label or something
         printf("<div class=\"hubTdbTree\">\n");
         printf("<div id='tracks%d'></div>", hubInfo->id); // div for the jstree for this hub's search result(s)
         printf("</div>\n");
         printHubOutputStructure(hubOut, hubInfo);
         }
+    printf("</td></tr>\n");
     }
 }
 
 int hubEntryCmp(const void *va, const void *vb)
 /* Compare to sort based on shortLabel */
 {
 const struct hubEntry *a = *((struct hubEntry **)va);
 const struct hubEntry *b = *((struct hubEntry **)vb);
 
 return strcasecmp(a->shortLabel, b->shortLabel);
 }
 
 
 void printHubList(struct slName *hubsToPrint, struct hash *hubLookup, struct hash *searchResultHash)
 /* Print out a list of hubs, possibly along with search hits to those hubs.
@@ -1146,63 +1144,59 @@
  */
 {
 printf("<FORM ACTION=\"%s\" id='publicHubForm' NAME=\"publicHubForm\">\n",  "../cgi-bin/hgGateway");
 cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on");
 cartSaveSession(cart);
 
 int count = 0;
 struct hubEntry *hubList = NULL;
 struct hubEntry *hubInfo;
 long slTime;
 long printOutputForHubTime;
 if (hubsToPrint != NULL)
     {
     printHubListHeader();
     
-    if (searchResultHash == NULL) // if not displaying search results, join the hub <tr>s into one table
-        printf("<table class='hubList'><tbody>\n");
     struct slName *thisHubName = NULL;
     for (thisHubName = hubsToPrint; thisHubName != NULL; thisHubName = thisHubName->next)
         {
         hubInfo = (struct hubEntry *) hashFindVal(hubLookup, thisHubName->name);
         if (hubInfo == NULL)
             {
             /* This shouldn't happen often, but maybe the search hits list was built from an outdated
              * search text file that includes hubs for which no info is available.
              * Skip this hub. */
             continue;
             }
         slAddHead(&hubList, hubInfo);
         }
     slSort(&hubList, hubEntryCmp);
     slTime = clock1000();
 
     for (hubInfo = hubList; hubInfo != NULL; hubInfo = hubInfo->next)
         {
         struct hubSearchText *searchResult = NULL;
         if (searchResultHash != NULL)
             {
             searchResult = (struct hubSearchText *) hashMustFindVal(searchResultHash, hubInfo->hubUrl);
             }
         printOutputForHub(hubInfo, searchResult, count);
         count++;
         }
     printOutputForHubTime = clock1000();
     if (measureTiming)
         printf("hgHubConnect: printOutputForHubTime before js execution: %lu millis<BR>\n", printOutputForHubTime - slTime);
-    if (searchResultHash == NULL)
-        printf("</tbody></table>\n");
     
     printHubListFooter();
     }
 if (hubsToPrint != NULL)
     {
     /* Write out the list of hubs in a single table inside a div that will be hidden by
      * javascript.  This table is used (before being hidden) to set common column widths for
      * the individual hub tables when they're split by detailed search results. */
     printf("<div id='hideThisDiv'>\n");
     printf("<table class='hubList' id='hideThisTable'><tbody>\n");
     for (hubInfo = hubList; hubInfo != NULL; hubInfo = hubInfo->next)
         {
         printOutputForHub(hubInfo, NULL, count);
         count++;
         }