34a45f462f1b0e73015f60354ded50644bf629b7 braney Wed Apr 15 13:03:18 2026 -0700 Apply colorOverride to track labels; add right-click "Change Track Color" dialog, refs #20460 Co-Authored-By: Claude Opus 4.6 (1M context) diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js index bc6c8e01b31..6813b8d7c4e 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -2483,30 +2483,34 @@ success: catchErrorOrDispatch, error: errorHandler, cache: true }); }); } else if (cmd === 'hgTrackUi_popup') { // Launches the popup but shields the ajax with a waitOnFunction popUp.hgTrackUi( rightClick.selectedMenuItem.id, false ); } else if (cmd === 'hgTrackUi_popup_description') { // Launches the popup but shields the ajax with a waitOnFunction popUp.hgTrackUi( rightClick.selectedMenuItem.id, true ); + } else if (cmd === 'changeTrackColor') { + + rightClick.showColorPicker(id); + } else if (cmd === 'hgTrackUi_follow') { url = "hgTrackUi?hgsid=" + getHgsid() + "&g="; rec = hgTracks.trackDb[id]; if (tdbHasParent(rec) && tdbIsLeaf(rec)) url += rec.parentTrack; else { // The button already has the ref var link = normed($( 'td#td_btn_'+ rightClick.selectedMenuItem.id ).children('a')); if (link) url = $(link).attr('href'); else url += rightClick.selectedMenuItem.id; } location.assign(url); @@ -2748,30 +2752,105 @@ if (rightClick.floatingMenuItem) { $('#img_data_' + rightClick.floatingMenuItem).parent().makeFloat( {x:"current",y:"current", speed: 'fast', alwaysVisible: true, alwaysTop: true}); } }, makeImgTag: function (img) { // Return img tag with explicit dimensions for img (dimensions are currently hardwired). // This fixes the "weird shadow problem when first loading the right-click menu" // seen in FireFox 3.X, which occurred b/c FF doesn't actually fetch the image until // the menu is being shown. return ""; }, + showColorPicker: function (trackName) + { // Show a small dialog with a spectrum color picker for changing track color + var rec = hgTracks.trackDb[trackName]; + if (!rec || !rec.defaultColor) + return; + var currentColor = (rec.colorOverrideOn && rec.colorOverride) ? + rec.colorOverride : rec.defaultColor; + var dialogId = "trackColorDialog"; + $("#" + dialogId).remove(); + $("body").append( + "
" + + "

Pick a new color for " + rec.shortLabel + ":

" + + "" + + " " + + "

" + + "
"); + $("#trackColorPicker").spectrum({ + color: currentColor, + showPalette: true, + showSelectionPalette: true, + showInitial: true, + showInput: true, + preferredFormat: "hex", + localStorageKey: "genomebrowser", + hideAfterPaletteSelect: true, + change: function(color) { + $("#trackColorText").val(color.toHexString()); + $("#trackColorOn").prop("checked", true); + } + }); + $("#trackColorText").on("change", function() { + $("#trackColorPicker").spectrum("set", $(this).val()); + $("#trackColorOn").prop("checked", true); + }); + $("#" + dialogId).dialog({ + modal: true, + title: "Change Track Color", + closeOnEscape: true, + resizable: false, + minWidth: 400, + buttons: { + "Apply": function() { + var color = $("#trackColorText").val(); + var isOn = $("#trackColorOn").is(":checked") ? "1" : "0"; + rec.colorOverride = color; + rec.colorOverrideOn = (isOn === "1"); + cart.setVars( + [trackName + ".colorOverride", trackName + ".colorOverrideOn"], + [color, isOn], null, false); + imageV2.requestImgUpdate(trackName, + trackName + ".colorOverride=" + encodeURIComponent(color) + + "&" + trackName + ".colorOverrideOn=" + isOn); + }, + "Ok": function() { + var color = $("#trackColorText").val(); + var isOn = $("#trackColorOn").is(":checked") ? "1" : "0"; + rec.colorOverride = color; + rec.colorOverrideOn = (isOn === "1"); + cart.setVars( + [trackName + ".colorOverride", trackName + ".colorOverrideOn"], + [color, isOn], null, false); + imageV2.requestImgUpdate(trackName, + trackName + ".colorOverride=" + encodeURIComponent(color) + + "&" + trackName + ".colorOverrideOn=" + isOn); + $(this).dialog("close"); + } + }, + close: function() { + $("#trackColorPicker").spectrum("destroy"); + $(this).remove(); + } + }); + }, // CGIs now use HTML tags, e.g. "Transcript: ENST00000297261.7
Strand:" mouseOverToLabel: function(title) { if (title.search(/Transcript: ?<[/]b>/) !== -1) { title = title.split("
")[0].split("
")[1]; } // for older UCSC genes tracks, the protein name is forced onto the item name if (title.search(/&hgg_prot=/) !== -1) { title = title.split("&hgg_prot=")[0]; } return title; }, // when "exonNumbers on", the mouse over text is not a good item description for the right-click menu @@ -3187,30 +3266,40 @@ } else { titleStr += "Merge items that span the current region"; } o[titleStr] = {onclick: function(menuItemClick, menuObject) { rightClick.hit(menuItemClick, menuObject, "toggleMerge", rec); return true; } }; } o[rightClick.makeImgTag("book.png")+" Track Description "+rec.shortLabel] = { onclick: function(menuItemClicked, menuObject) { rightClick.hit(menuItemClicked, menuObject, "hgTrackUi_popup_description"); return true; } }; + if (rec.defaultColor) { + menu.push(o); + o = {}; + o[rightClick.makeImgTag("wrench.png")+" Change Track Color"] = { + onclick: function(menuItemClicked, menuObject) { + rightClick.hit(menuItemClicked, menuObject, "changeTrackColor"); + return true; } + }; + } + menu.push($.contextMenu.separator); menu.push(o); } menu.push($.contextMenu.separator); if (hgTracks.highlight && rightClick.clickedHighlightIdx!==null) { var currentlySeen = ($('#highlightItem').length > 0); o = {}; // Jumps to highlight when not currently seen in image var text = (currentlySeen ? " Zoom" : " Jump") + " to highlight"; o[rightClick.makeImgTag("highlightZoom.png") + text] = { onclick: rightClick.makeHitCallback('jumpToHighlight') }; if ( currentlySeen ) { // Remove only when seen