8593c40cb74ab6ee9f2318056626305d9d9544d3
braney
  Fri Apr 10 12:54:44 2026 -0700
Fix color picker from code review, refs #37329, refs #20460

- Replace Spectrum JS color picker with native HTML5 color input,
matching existing Hi-C picker
- Color saved on form submit, not immediately via AJAX
- Add checkbox to enable/disable color override; auto-checks when
user picks a color
- Gate color picker behind hg.conf showColorPicker=on (off by default)
- Only show picker for non-composite tracks that support it: bed,
bigBed, genePred, bigGenePred, wig, bigWig, rmsk, interact,
bigInteract, bigLolly, vcfTabix, vcf
- Add colorFromCart calls to interact, lolly, vcf phased, and pgSnp
drawing code
- Revert hui.js Spectrum changes from cfeb4d4 (no longer needed)
- Use htmlColorForCode()/htmlColorToRGB() from htmlColor.h instead of
hand-rolled hex parsing in colorFromCart

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

diff --git src/hg/hgTracks/bedTrack.c src/hg/hgTracks/bedTrack.c
index 465d76fdfe6..33a6d8e244f 100644
--- src/hg/hgTracks/bedTrack.c
+++ src/hg/hgTracks/bedTrack.c
@@ -7,30 +7,31 @@
 #include "jksql.h"
 #include "bed.h"
 #include "hdb.h"
 #include "bedCart.h"
 #include "bbiFile.h"
 #include "bigBed.h"
 #include "hgTracks.h"
 #include "cds.h"
 #include "bedTabix.h"
 #include "obscure.h"
 #include "bigBedFilter.h"
 #include "bigBedLabel.h"
 #include "snake.h"
 #include "liftOver.h"
 #include "quickLift.h"
+#include "htmlColor.h"
 
 #define SEQ_DELIM '~'
 
 struct bed *bedLoadPairedTagAlign(char **row)
 /* Load first six fields of bed.
  * Add ~seq1~seq2 to end of name
  * Then remove the sequence to extra field when we convert to linkedFeature.
  * Assumes seq1 and seq2 are in row[6] and row[7], as they would be with a
  * pairedTagAlign type (hg/lib/encode/pairedTagAlign.as). It would be good to be
  * able to check these columns exist but we dont have the sqlResult here. */
 {
 char buf[1024];
 struct bed *ret = bedLoad6(row);
 safef(buf, sizeof(buf), "%s%c%s%c%s", ret->name, SEQ_DELIM, row[6], SEQ_DELIM, row[7]);
 freez(&(ret->name));
@@ -624,41 +625,43 @@
         }
     }
 
 slReverse(&lfList);
 if(tg->extraUiData)
     filterBed(tg, &lfList);
 slSort(&lfList, linkedFeaturesCmp);
 tg->items = lfList;
 filterItemsOnNames(tg);
 maybeLoadSnake(tg);   // if we're in snake mode, change the methods
 }
 
 Color colorFromCart(struct track *tg, Color color)
 /* Return the RGB color from the cart setting 'colorOverride' or just return color */
 {
+if (!cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, "colorOverrideOn", FALSE))
+    return color;
 char *hexColorStr = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE, "colorOverride");
-if (hexColorStr==NULL || isEmpty(hexColorStr))
+if (isEmpty(hexColorStr))
     return color;
-if (hexColorStr[0]=='#')
-    hexColorStr++;
-if (strlen(hexColorStr)!=6)
+unsigned rgb;
+if (!htmlColorForCode(hexColorStr, &rgb))
     return color;
-long rgb = strtol(hexColorStr,NULL,16); // Big and little Endians
+int r, g, b;
+htmlColorToRGB(rgb, &r, &g, &b);
 tg->itemColor = NULL;
 tg->itemNameColor = NULL;
-return MAKECOLOR_32( ((rgb>>16)&0xff), ((rgb>>8)&0xff), (rgb&0xff) );
+return MAKECOLOR_32(r, g, b);
 }
 
 void bedDrawSimpleAt(struct track *tg, void *item,
 	struct hvGfx *hvg, int xOff, int y,
 	double scale, MgFont *font, Color color, enum trackVisibility vis)
 /* Draw a single simple bed item at position. */
 {
 struct bed *bed = item;
 int heightPer = tg->heightPer;
 int s = max(bed->chromStart, winStart), e = min(bed->chromEnd, winEnd);
 if (s > e)
     return;
 int x1 = round((s-winStart)*scale) + xOff;
 int x2 = round((e-winStart)*scale) + xOff;
 int w = x2 - x1;