668110379c7c18bc75dd2db8747821b387fb28d6
chmalee
  Fri Jan 27 10:22:57 2023 -0800
Redraw barChart svgs on the client so the column widths can be wide enough for labels, refs #28439

diff --git src/hg/hgc/barChartClick.c src/hg/hgc/barChartClick.c
index ca51ddc..a9b03fe 100644
--- src/hg/hgc/barChartClick.c
+++ src/hg/hgc/barChartClick.c
@@ -14,30 +14,31 @@
 #include "hgc.h"
 #include "trackHub.h"
 #include "memgfx.h"
 #include "hgColors.h"
 #include "fieldedTable.h"
 
 #include "barChartBed.h"
 #include "barChartCategory.h"
 #include "barChartData.h"
 #include "barChartSample.h"
 #include "barChartUi.h"
 #include "hgConfig.h"
 #include "facetedBar.h"
 #include "pipeline.h"
 #include "chromAlias.h"
+#include "jsHelper.h"
 
 #define EXTRA_FIELDS_SIZE 256
 
 struct barChartItemData
 /* Measured value for a sample and the sample category at a locus.
  * Used for barChart track details (boxplot) */
     {
     struct barChartItemData *next;  /* Next in singly linked list. */
     char *sample;	/* Sample identifier */
     char *category;     /* Sample category (from barChartSample table  or barChartSampleUrl file) */
     double value;	/* Measured value (e.g. expression level) */
     };
 
 struct barChartPlusRow
 /* Keep original row around for url processing */
@@ -418,30 +419,31 @@
 return longest * 1.02;
 }
 
 void deunderbarColumn(struct fieldedTable *ft, int fieldIx)
 /* Ununderbar all of a column inside table because space/underbar gets
  * so confusing */
 {
 struct fieldedRow *row;
 for (row = ft->rowList; row != NULL; row = row->next)
     replaceChar(row->row[fieldIx], '_', ' ');
 }
 
 static void svgBarChart(struct barChartBed *chart, struct trackDb *tdb, double maxVal, char *metric)
 /* Plot bar chart without quartiles or anything fancy just using SVG */
 {
+jsIncludeFile("hgc.js", NULL);
 puts("<p>");
 /* Load up input labels, color, and data */
 struct barChartCategory *categs = barChartUiGetCategories(database, tdb, NULL);
 int categCount = slCount(categs);
 if (categCount != chart->expCount)
     {
     warn("Problem in %s barchart track. There are %d categories in trackDb and %d in data",
 	tdb->track, categCount, chart->expCount);
     return;
     }
 
 char *statsFile = hReplaceGbdb(trackDbSetting(tdb, "barChartStatsUrl"));
 struct hash *statsHash = NULL;
 int countStatIx = 0;
 double statsSize = 0.0;
@@ -462,77 +464,77 @@
 double borderSize = 1.0;
 
 double headerHeight = heightPer + 2*borderSize;
 double innerHeight=heightPer-borderSize;
 double labelWidth = longestLabelSize(categs) + 9;  // Add some because size is just estimate
 if (labelWidth > totalWidth/2) labelWidth = totalWidth/2;  // Don't let labels take up more than half
 double patchWidth = heightPer;
 double labelOffset = patchWidth + 2*borderSize;
 double statsOffset = labelOffset + labelWidth;
 double barOffset = statsOffset + statsSize;
 double statsRightOffset = barOffset - 9;
 double barNumLabelWidth = estimateStringWidth(" 1234.000");
 double barMaxWidth = totalWidth-barOffset -barNumLabelWidth ;
 double totalHeight = headerHeight + heightPer * categCount + borderSize;
 
-printf("<svg width=\"%g\" height=\"%g\">\n", totalWidth, totalHeight);
+printf("<svg id='svgBarChart' width=\"%g\" height=\"%g\">\n", totalWidth, totalHeight);
 
 /* Draw header */
 printf("<rect width=\"%g\" height=\"%g\" style=\"fill:#%s\"/>\n", totalWidth, headerHeight, HG_COL_HEADER);
 char *sampleLabel = trackDbSettingOrDefault(tdb, "barChartLabel", "Sample");
-printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%s</text>\n",
+printf("<text class=\"sampleLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\">%s</text>\n",
     labelOffset, innerHeight-1, innerHeight-1, sampleLabel);
 if (statsSize > 0.0)
-    printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\" text-anchor=\"end\">%s</text>\n",
+    printf("<text class=\"statsLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\" text-anchor=\"end\">%s</text>\n",
 	statsRightOffset, innerHeight-1, innerHeight-1, "N");
-printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%s %s</text>\n",
+printf("<text class=\"valueLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\">%s %s</text>\n",
     barOffset, innerHeight-1, innerHeight-1, metric, "Value");
 
 /* Set up clipping path for the pesky labels, which may be too long */
 printf("<clipPath id=\"labelClip\"><rect x=\"%g\" y=\"0\" width=\"%g\" height=\"%g\"/></clipPath>\n",
     labelOffset, barOffset-labelOffset, totalHeight);
 
 double yPos = headerHeight;
 struct barChartCategory *categ;
 int i;
 for (i=0, categ=categs; i<categCount; ++i , categ=categ->next, yPos += heightPer)
     {
     double score = chart->expScores[i];
     double barWidth = 0;
     if (maxVal > 0.0)
 	barWidth = barMaxWidth * score/maxVal;
     char *deunder = cloneString(categ->label);
     replaceChar(deunder, '_', ' ');
     printf("<rect x=\"0\" y=\"%g\" width=\"15\" height=\"%g\" style=\"fill:#%06X\"/>\n",
 	yPos, innerHeight, categ->color);
-    printf("<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n",
-	barOffset, yPos, barWidth, innerHeight, categ->color);
+    printf("<rect id=\"bar%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n",
+	i+1, barOffset, yPos, barWidth, innerHeight, categ->color);
     if (i&1)  // every other time
-	printf("<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n",
+	printf("<rect class=\"sampleBand\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n",
 	    labelOffset, yPos, labelWidth+statsSize, innerHeight, 0xFFFFFF);
-    printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\" clip-path=\"url(#labelClip)\"\">%s</text>\n",
+    printf("<text class=\"sampleLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\" clip-path=\"url(#labelClip)\"\">%s</text>\n",
  	labelOffset, yPos+innerHeight-1, innerHeight-1, deunder);
     if (statsSize > 0.0)
 	{
 	struct fieldedRow *fr = hashFindVal(statsHash, deunder);
 	if (fr != NULL)
 	    {
-	    printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\" text-anchor=\"end\">%s</text>\n",
+	    printf("<text class=\"statsLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\" text-anchor=\"end\">%s</text>\n",
 		statsRightOffset, yPos+innerHeight-1, innerHeight-1, fr->row[countStatIx]);
 	    }
 	}
-    printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%5.3f</text>\n",
+    printf("<text class=\"valueLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\">%5.3f</text>\n",
 	barOffset+barWidth+2, yPos+innerHeight-1, innerHeight-1, score);
     }
 printf("</svg>");
 }
 
 
 static void printBarChart(char *item, struct barChartBed *chart, struct trackDb *tdb,
     double maxVal, char *metric)
 /* Plot bar chart without expressionMatrix or R plots*/
 {
 char *statsFile = hReplaceGbdb(trackDbSetting(tdb, "barChartStatsUrl"));
 char *facets = trackDbSetting(tdb, "barChartFacets");
 if (facets != NULL && statsFile != NULL)
     facetedBarChart(item, chart, tdb, maxVal, statsFile, facets, metric);
 else