a9b3f2ba629176ff781c64587544b78ddfa1557b
kent
  Mon Dec 13 18:30:59 2021 -0800
Making merge/unmerge buttons jump page on return to where they are rather than to top of page.  Saves scrolling when merging/unmerging a lot of things.

diff --git src/hg/lib/tablesTables.c src/hg/lib/tablesTables.c
index 755e1ff..244ff46 100644
--- src/hg/lib/tablesTables.c
+++ src/hg/lib/tablesTables.c
@@ -406,30 +406,40 @@
 
 	    // last page
 	    printf("   ");
 	    safef(id, sizeof id, "%s_last", varPrefix);
 	    printf("<a href='#' id='%s'>&#9197;</a>", id);
 	    jsOnEventByIdF("click", id, 
 		"$('[name=%s_page]').val('%d');\n"
 		"event.target.closest('form').submit();\n"
 		, varPrefix, totalPages);
 
 	    }
 	}
      }
 }
 
+static void createSelfId(char *varPrefix, char *fieldName, 
+	char *val, char *selfId, int selfIdSize)
+{
+if (val == NULL)
+    safef(selfId, selfIdSize, "%s_self_a_%s", varPrefix, fieldName);
+else
+    safef(selfId, selfIdSize, "%s_self_a_%s_%s", varPrefix, fieldName, val);
+subChar(selfId, ' ', '_');
+}
+
 void webFilteredFieldedTable(struct cart *cart, struct fieldedTable *table, 
     char *visibleFieldList, char *returnUrl, char *varPrefix,
     int maxLenField, struct hash *tagOutputWrappers, void *wrapperContext,
     boolean withFilters, char *pluralInstructions, 
     int pageSize, int facetUsualSize,
     struct fieldedTableSegment *largerContext, struct hash *suggestHash, 
     struct facetField **ffArray, char *visibleFacetList,
     void (*addFunc)(int), boolean facetMergeOk )
 /* Show a fielded table that can be sorted by clicking on column labels and optionally
  * that includes a row of filter controls above the labels .
  * The maxLenField is maximum character length of field before truncation with ...
  * Pass in 0 for no max. */
 {
 if (strchr(returnUrl, '?') == NULL)
      errAbort("Expecting returnUrl to include ? in showFieldedTable\nIt's %s", returnUrl);
@@ -495,32 +505,31 @@
 				"&%s_facet_fieldName=%s|url|"
 				"&%s_facet_fieldVal=%s|url|"
 				"&%s_page=1'"
 				">",
 			    returnUrl, varPrefix,
 			    op, varPrefix, field->fieldName, varPrefix, val->val, varPrefix
 			    );
 			htmlDyStringPrintf(facetBar, "%s (%d)</a>", 
 			    naForEmpty(val->val), val->selectCount);
 			htmlDyStringPrintf(facetBar, "</dd>\n");
 			}
 		    }
 		slFreeList(&valListCopy);
 		
 		htmlDyStringPrintf(facetBar, "</span></span>\n");
-		}
-	    }
+		} }
 	else
 	    {
 	    anyMerged = TRUE;
 	    htmlDyStringPrintf(facetBar, 
 		"<span class='card facet-card' style='display: inline-block;'>"
 		"<span class='card-body'>\n");
 	    htmlDyStringPrintf(facetBar, "<dt style='display: inline-block;'>\n");
 	    htmlDyStringPrintf(facetBar, "<h6 class='card-title'>%s</h6></dt>\n", 
 		vis->name);
 	    htmlDyStringPrintf(facetBar, " <a class='btn btn-secondary' href='%s"
 		    "&%s_facet_op=%s|none|"
 		    "&%s_facet_fieldName=%s|url|"
 		    "&%s_facet_fieldVal=%s|url|"
 		    "&%s_page=1' "
 		    ">", 
@@ -580,59 +589,60 @@
     }
 
 printf("<div class='row'>\n"); // parent container
 
 if (visibleFacetList)
     {
     // left column
     printf("<div class='col-xs-6 col-sm-4 col-md-4 col-lg-3 col-xl-3'>\n");
 
     struct slName *visList = slNameListFromComma(visibleFacetList);
     struct slName *vis;
     for (vis = visList; vis != NULL; vis = vis->next)
 	{
 	char *fieldName = vis->name;
 	char selfId[256];
-	safef(selfId, sizeof(selfId), "%s_self_a_%s", varPrefix, fieldName);
-	subChar(selfId, ' ', '_');
+	createSelfId(varPrefix, fieldName, NULL, selfId, sizeof(selfId));
 
 	/* Work on facet field label line */
 	htmlPrintf("<div id=\"%s\" class='card facet-card'><div class='card-body'>\n", selfId);
 	htmlPrintf("<h6 class='card-title'>%s",vis->name);
 
 	int f = fieldedTableFindFieldIx(table, fieldName);
 	char *op = "unmerge";
 	struct facetField *field = NULL;
 	if (f >= 0)
 	    {
 	    field = ffArray[f];
 	    if (!field->isMerged)
 	        op = "merge";
 	    }
 
 	/* Write merge/unmerge link and number of categories */
 	if (facetMergeOk)
 	    {
+	    char selfId[256];
+	    createSelfId(varPrefix, fieldName, NULL, selfId, sizeof(selfId));
 	    htmlPrintf("<span style='float:right'>");
 	    htmlPrintf("<a class='btn btn-secondary' href='%s"
 		    "&%s_facet_op=%s|none|"
 		    "&%s_facet_fieldName=%s|url|"
 		    "&%s_facet_fieldVal=%s|url|"
-		    "&%s_page=1' "
+		    "&%s_page=1#%s' "
 		    ">", 
 		    returnUrl, varPrefix, op, varPrefix, fieldName, 
-		    varPrefix, "", varPrefix);
+		    varPrefix, "", varPrefix, selfId);
 	    htmlPrintf("%s", op);
 
 	    if (field != NULL && sameString(op, "merge"))
 		{
 		int selectedFieldCount = facetFieldCountSelected(field);
 		htmlPrintf(" %d", selectedFieldCount);
 		}
 	    htmlPrintf("</a></span>");
 	    }
 
 	/* CLose up facet field label line */
 	htmlPrintf("</h6><dl>\n");
 
 	if (field != NULL)
 	    {
@@ -664,33 +674,32 @@
 		{
 		boolean specificallySelected = (val->selected && !field->allSelected);
 		if ((val->selectCount > 0 && 
 		    (field->showAllValues || valuesShown < facetUsualSize) && 
 		    !field->isMerged)
 		    || specificallySelected)
 		    {
 		    ++valuesShown;
 		    ++extraAnchorPos;
 		    char *op = "add";
 		    if (specificallySelected)
 			op = "remove";
 		    printf("<dd class=\"facet\"");
 		    if (extraAnchorPos >= extraAnchorPeriod)
 			{
-			safef(selfId, sizeof(selfId), "%s_self_a_%s_%s", varPrefix, vis->name, 
-			    val->val);
-			subChar(selfId, ' ', '_');
+			char selfId[256];
+			createSelfId(varPrefix, vis->name, val->val, selfId, sizeof(selfId));
 			printf(" id=\"%s\"", selfId);
 			extraAnchorPos= 0;
 			}
 		    printf(">\n");
 		    htmlPrintf("<input type=checkbox value=%s class=ttFsCheckBox %s>&nbsp;",
 			specificallySelected ? "true" : "false", 
 			specificallySelected ? "checked" : "");
 		    htmlPrintf("<a href='%s"
 			    "&%s_facet_op=%s|none|"
 			    "&%s_facet_fieldName=%s|url|"
 			    "&%s_facet_fieldVal=%s|url|"
 			    "&%s_page=1#%s' "
 			    ">",
 			returnUrl, varPrefix,
 			op, varPrefix, field->fieldName, varPrefix, val->val, varPrefix, selfId
@@ -711,32 +720,32 @@
 		htmlPrintf("<dd><a href='%s"
 			"&%s_facet_op=%s|url|"
 			"&%s_facet_fieldName=%s|url|"
 			"&%s_facet_fieldVal=%s|url|"
 			"&%s_page=1#%s' "
 			">See %d More</a></dd>\n",
 		    returnUrl, varPrefix, op, 
 		    varPrefix, field->fieldName, varPrefix, "", 
 		    varPrefix, selfId, valuesNotShown
 		    );
 		}
 
 	    // show "See Fewer" link when facet has lots of values
 	    if (field->showAllValues && valuesShown >= facetUsualSize)
 		{
-		safef(selfId, sizeof(selfId), "%s_self_a_%s", varPrefix, vis->name);
-		subChar(selfId, ' ', '_');
+		char selfId[256];
+		createSelfId(varPrefix, vis->name, NULL, selfId, sizeof(selfId));
 		char *op = "showSomeValues";
 		htmlPrintf("<dd><a href='%s"
 			"&%s_facet_op=%s|url|"
 			"&%s_facet_fieldName=%s|url|"
 			"&%s_facet_fieldVal=%s|url|"
 			"&%s_page=1#%s' "
 			">%s</a></dd>\n",
 		    returnUrl, varPrefix, op, varPrefix, field->fieldName, varPrefix, "", varPrefix,
 		    selfId, "See Fewer"
 		    );
 		}
 	    }
 	htmlPrintf("</div></div>\n");
 	}
     printf("</div>\n");