e6eaaaa2b64a0ac14f17f5011f27f294d5287a23
lrnassar
  Wed Sep 9 16:30:48 2026 -0700
Escape the ampersands in the BLAT share box and rename dialog hgSession hrefs. Feedback from CR. refs #38292

diff --git src/hg/js/hgBlat.js src/hg/js/hgBlat.js
index 6f9923b1ea0..e0ef26a2c03 100644
--- src/hg/js/hgBlat.js
+++ src/hg/js/hgBlat.js
@@ -296,31 +296,31 @@
     box.style.display = 'flex';
     if (msg) {
         box.innerHTML = '<span class="gbShareMsg gbShareFull" style="color:#a00">' +
             htmlEncode(msg) + '</span>';
         return;
     }
     if (!url) {
         box.innerHTML = '<span class="gbShareMsg gbShareFull">Creating link…</span>';
         return;
     }
     box.innerHTML =
         '<span class="gbShareMsg gbShareFull">Anyone with this <b>shareable link</b> can open ' +
         'these BLAT results. It stores only the results, not your other tracks or settings. The ' +
         'link remains valid for years; to keep your results permanently, save them into a ' +
         `<a href="hgSession?db=${encodeURIComponent(hgBlatData.config.db || '')}` +
-        `&hgsid=${encodeURIComponent(hgBlatData.config.hgsid || '')}">Session</a>.</span>` +
+        `&amp;hgsid=${encodeURIComponent(hgBlatData.config.hgsid || '')}">Session</a>.</span>` +
         '<input id="gbShareInput" class="gbShareInput" type="text" readonly>' +
         '<button type="button" class="gbPill" id="blatShareCopy" title="Copy the link to the clipboard">Copy</button>';
     var inp = document.getElementById('gbShareInput');
     inp.value = url;
     inp.focus();
     inp.select();
     $('#blatShareCopy').on('click', function() {
         inp.select();
         if (navigator.clipboard) { navigator.clipboard.writeText(url); }
         else { document.execCommand('copy'); }
         this.textContent = 'Copied';
     });
 }
 
 function blatShareLink() {
@@ -367,31 +367,31 @@
             if (blatShareBoxOpen(box))
                 blatShowShareBox(box, null, 'Could not reach the server. Please try again.');
         });
 }
 
 // ---- Rename BLAT track (modal) -------------------------------------------
 // The results custom track is built (and renamed) by hgBlat.c's inline code, which exposes a small
 // window.blatRenameCt(name, description) helper (it POSTs to hgc's buildBigPsl and rebuilds the
 // track).  We reuse that helper (no new endpoint), just swapping its old inline toggle-form UI for a
 // proper modal dialog.  The current name/description come from cfg (hgBlat.c), not a global, so this
 // does not depend on any generic page-global.
 
 function blatRenameModalHtml(cfg) {
     // hgSession link is relative (same /cgi-bin/), carrying db + hgsid so the session page opens in
     // this assembly and cart.
-    var sessionUrl = `hgSession?db=${encodeURIComponent(cfg.db)}&hgsid=${encodeURIComponent(cfg.hgsid)}`;
+    var sessionUrl = `hgSession?db=${encodeURIComponent(cfg.db)}&amp;hgsid=${encodeURIComponent(cfg.hgsid)}`;
     return '<div id="gbModalBg" class="gbModalBg" style="display:none">' +
         '<div class="gbModal" role="dialog" aria-modal="true" aria-labelledby="gbModalTitle">' +
         '<div class="gbModalTitle" id="gbModalTitle">Rename BLAT Track</div>' +
         '<div class="gbModalText">Every BLAT result is stored in its own track in the Genome ' +
         'Browser, which you can rename here. Results will disappear after 2 days unless ' +
         `they are saved into a <a href="${sessionUrl}">Session link</a>.</div>` +
         '<label class="gbModalLabel" for="blatRenameName">Track name</label>' +
         '<input id="blatRenameName" class="gbModalInput" type="text" maxlength="80">' +
         '<label class="gbModalLabel" for="blatRenameDesc">Description</label>' +
         '<input id="blatRenameDesc" class="gbModalInput" type="text" maxlength="120">' +
         '<div class="gbModalBtns">' +
         '<button type="button" class="gbPill" id="blatRenameCancel">Cancel</button>' +
         '<button type="button" class="gbPill primary" id="blatRenameOk">OK</button>' +
         '</div></div></div>';
 }