94f9b53d3db05371699a8fae11407acf0b30e02f braney Wed Jul 8 16:22:22 2026 -0700 Fix three base-position ruler click issues: show "1 base" instead of "0 bases" at single-base zoom, make single clicks recenter symmetrically instead of drifting one base left, and stop a click on the ruler track's grey side-label strip from hijacking the config popup to do a zoom. refs #27113 diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js index 31a8467ac00..24ea18e429b 100644 --- src/hg/js/hgTracks.js +++ src/hg/js/hgTracks.js @@ -481,32 +481,37 @@ break; } } } return {chromStart : virtStart, chromEnd : virtEnd}; }, selectionPixelsToBases: function (img, selection) { // Convert selection x1/x2 coordinates to chromStart/chromEnd. return genomePos.pixelsToBases(img, selection.x1, selection.x2, hgTracks.winStart, hgTracks.winEnd, true); }, update: function (img, selection, singleClick) { + // For a drag-select keep the half-base offset (addHalfBp) so an edge that + // ends just before a base does not count that base. For a single click turn + // it off so both edges resolve to the same base under the pointer: with it on, + // at single-base zoom a left click drifted one base left while a right click + // could not move at all. var pos = genomePos.pixelsToBases(img, selection.x1, selection.x2, - hgTracks.winStart, hgTracks.winEnd, true); + hgTracks.winStart, hgTracks.winEnd, !singleClick); // singleClick is true when the mouse hasn't moved (or has only moved a small amount). if (singleClick) { var center = (pos.chromStart + pos.chromEnd)/2; pos.chromStart = Math.floor(center - hgTracks.newWinWidth/2); pos.chromEnd = pos.chromStart + hgTracks.newWinWidth; // clip if (pos.chromStart < hgTracks.chromStart) pos.chromStart = hgTracks.chromStart; // usually 1 if (pos.chromEnd > hgTracks.chromEnd) pos.chromEnd = hgTracks.chromEnd; // usually virt chrom size // save current position so that that it may be restored after highlight or cancel. genomePos.original = genomePos.getOriginalPos(); genomePos.originalSize = $('#size').text().replace(/,/g, ""); // strip out any commas @@ -2410,30 +2415,40 @@ else $(this).hide(); $('body').css('cursor', ''); // Occasionally wait cursor got left behind $("#hlColorPicker").spectrum("hide"); } }); $(dragSelectDialog).dialog('open'); }, selectEnd: function (img, selection, event) { var now = new Date(); var doIt = false; var rulerClicked = selection.y1 <= hgTracks.rulerClickHeight; // = drag on base position track (no shift) + // A single click on the grey side-label/config strip has its x clamped into the + // data area by imgAreaSelect, so without this test it looks like a ruler click and + // performs the zoom instead of opening the base-position track's config popup (#27113). + // Use the raw mouse x (getXLimits gives the data-area bounds) to spot a label-strip + // click and let it fall through to the normal config handler. + if (rulerClicked && selection.event) { + var dataXLimits = genomePos.getXLimits($(img), 0); + if (selection.event.pageX < dataXLimits[0] || selection.event.pageX > dataXLimits[1]) + rulerClicked = false; + } if (dragSelect.originalCursor) jQuery('body').css('cursor', dragSelect.originalCursor); if (dragSelect.escPressed) return false; // ignore releases outside of the image rectangle (allowing a 10 pixel slop) if (genomePos.check(img, selection)) { // ignore single clicks that aren't in the top of the image // (this happens b/c the clickClipHeight test in dragSelect.selectStart // doesn't occur when the user single clicks). doIt = (dragSelect.startTime !== null || rulerClicked); } if (doIt) { // dragSelect.startTime is null if mouse has never been moved var singleClick = ( (selection.x2 === selection.x1)