25f258c7fdfbdf417a917fcd00fff78d698def9b
chmalee
  Fri Aug 30 12:01:24 2024 -0700
Big run through of changes to accomodate jquery 3.7.1 upgrade. Most of the changes are replacing the event methods with a change to .on(event, function(..)). A couple more changes are removing calls to jquery.type(). Also fixes various plugins and styles

diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index ad3020d..a0416eb 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -965,51 +965,51 @@
     expandAllGroups: function (newState)
     {   // Set visibility of all track groups to newState (true means expanded).
         // This code also modifies the corresponding hidden fields and the gif's of the +/- img tag.
         imageV2.markAsDirtyPage();
         $(".toggleButton[id$='_button']").each( function (i) {  
             // works for old img type AND new BUTTONS_BY_CSS      // - 7: clip '_button' suffix
             vis.toggleForGroup(this,this.id.substring(0,this.id.length - 7),newState);
         });
         return false;
     },
     
     initForAjax: function()
     {   // To better support the back-button, it is good to eliminate extraneous form puts
         // Towards that end, we support visBoxes making ajax calls to update cart.
         var sels = $('select.normalText,select.hiddenText');
-        $(sels).change(function() {
+        $(sels).on("change", function() {
             var track = $(this).attr('name');
             if ($(this).val() === 'hide') {
                 var rec = hgTracks.trackDb[track];
                 if (rec)
                     rec.visibility = 0;
                 // else Would be nice to hide subtracks as well but that may be overkill
                 $(document.getElementById('tr_' + track)).remove();
                 cart.updateSessionPanel();
                 imageV2.drawHighlights();
                 $(this).attr('class', 'hiddenText');
             } else
                 $(this).attr('class', 'normalText');
             
             cart.setVars([track], [$(this).val()]);
             imageV2.markAsDirtyPage();
             return false;
         });
         // Now we can rid the submt of the burden of all those vis boxes
         var form = $('form#TrackForm');
-        $(form).submit(function () {
+        $(form).on("submit", function () {
             $('select.normalText,select.hiddenText').prop('disabled',true);
         });
         $(form).attr('method','get');
     },
 
     restoreFromBackButton: function()
     // Re-enabling vis dropdowns is necessary because initForAjax() disables them on submit.
     {
         $('select.normalText,select.hiddenText').prop('disabled',false);
     }
 };
 
   ////////////////////////////////////////////////////////////
  // dragSelect is also known as dragZoom or shift-dragZoom //
 ////////////////////////////////////////////////////////////
@@ -1174,35 +1174,35 @@
                              "<li>Hold <b>Ctrl+drag</b> (Windows) or <b>Cmd+drag</b> (Mac) to zoom" +
                              "<li>To cancel, press <tt>Esc</tt> anytime during the drag" +
                              "<li>Using the keyboard, highlight the current position with <tt>h then m</tt>" +
                              "<li>Clear all highlights with View - Clear Highlights or <tt>h then c</tt>" +
                              "<li>Clear specific highlights with right click &gt; Remove highlight" +
                              "<li>To merely save the color for the next keyboard or right-click &gt; Highlight operations, click 'Save Color' below" +
                              "</ul></p>");
             makeHighlightPicker("hlColor", document.getElementById("dragSelectDialog"), null);
             $("#dragSelectDialog").append("<input style='float:left' type='checkbox' id='disableDragHighlight'>" + 
                              "<span style='border:solid 1px #DDDDDD; padding:3px;display:inline-block' id='hlNotShowAgainMsg'>Don't show this again and always zoom with shift.<br>" + 
                              "Re-enable via 'View - Configure Browser' (<tt>c then f</tt>)</span></p>"+ 
                              "Selected chromosome position: <span id='dragSelectPosition'></span>");
             dragSelectDialog = $("#dragSelectDialog")[0];
             // reset value
             // allow to click checkbox by clicking on the label
-            $('#hlNotShowAgainMsg').click(function() { $('#disableDragHighlight').click();});
+            $('#hlNotShowAgainMsg').on("click", function() { $('#disableDragHighlight').trigger("click");});
             // click "add highlight" when enter is pressed in color input box
-            $("#hlColorInput").keyup(function(event){
+            $("#hlColorInput").on("keyup", function(event){
                 if(event.keyCode == 13){
-                    $(".ui-dialog-buttonset button:nth-child(3)").click();
+                    $(".ui-dialog-buttonset button:nth-child(3)").trigger("click");
                 }
             });
         }
 
         if (hgTracks.windows) {
             var i,len;
             var newerPosition = newPosition;
             if (hgTracks.virtualSingleChrom && (newPosition.search("multi:")===0)) {
                 newerPosition = genomePos.disguisePosition(newPosition);
             }
             var str = newerPosition + "<br>\n";
             var str2 = "<br>\n";
             str2 += "<ul style='list-style-type:none; max-height:200px; padding:0; width:80%; overflow:hidden; overflow-y:scroll;'>\n";
             var pos = parsePosition(newPosition);
             var start = pos.start - 1;
@@ -1274,31 +1274,31 @@
                         var hlColor = $("#hlColorInput").val();
                         dragSelect.highlightThisRegion(newPosition, true, hlColor);
                         $(this).dialog("close");
                     },
                     "Save Color": function() {
                         var hlColor = $("#hlColorInput").val();
                         dragSelect.saveHlColor( hlColor );
                         $(this).dialog("close");
                     },
                     "Cancel": function() {
                         $(this).dialog("close");
                     }
                 },
 
                 open: function () { // Make zoom the focus/default action
-                   $(this).parents('.ui-dialog-buttonpane button:eq(0)').focus(); 
+                   $(this).parents('.ui-dialog-buttonpane button:eq(0)').trigger("focus");
                 },
 
                 close: function() {
                     // All exits to dialog should go through this
                     $(imageV2.imgTbl).imgAreaSelect({hide:true});
                     if ($(this).dialog("option", "revertToOriginalPos"))
                         genomePos.revertToOriginalPos();
                     if ($("#disableDragHighlight").prop('checked'))
                         $(this).remove();
                     else
                         $(this).hide();
                     $('body').css('cursor', ''); // Occasionally wait cursor got left behind
                     $("#hlColorPicker").spectrum("hide");
                 }
         });
@@ -1385,39 +1385,39 @@
                 maxX : xLimits[1],
                 selectionColor:  'blue',
                 outerColor:      '',
                 minHeight:       imgHeight,
                 maxHeight:       imgHeight,
                 onSelectStart:   dragSelect.selectStart,
                 onSelectChange:  dragSelect.selectChange,
                 onSelectEnd:     dragSelect.selectEnd,
                 autoHide:        false, // gets hidden after possible dialog
                 movable:         false,
                 clickClipHeight: heights
             }));
 
             // remove any ongoing drag-selects when the esc key is pressed anywhere for this document
             // This allows to abort zooming / highlighting
-            $(document).keyup(function(e){
+            $(document).on("keyup", function(e){
                 if(e.keyCode === 27) {
                     $(imageV2.imgTbl).imgAreaSelect({hide:true});
                     dragSelect.escPressed = true;
                 }
             });
 
             // hide and redraw all current highlights when the browser window is resized
-            $(window).resize(function() {
+            $(window).on("resize", function() {
                 $(imageV2.imgTbl).imgAreaSelect({hide:true});
                 imageV2.drawHighlights();
             });
 
         }
     }
 };
 
   /////////////////////////////////////
  //// Chrom Drag/Zoom/Expand code ////
 /////////////////////////////////////
 jQuery.fn.chromDrag = function(){
 this.each(function(){
     // Plan:
     // mouseDown: determine where in map: convert to img location: pxDown
@@ -1436,70 +1436,70 @@
     var mouseIsDown   = false;
     var mouseHasMoved = false;
     var hilite = null;
 
     initialize();
 
     function initialize(){
 
         findDimensions();
 
         if (chr.top === -1)
             warn("chromIdeo(): failed to register "+this.id);
         else {
             hiliteSetup();
 
-            $('area.cytoBand').unbind('mousedown');  // Make sure this is only bound once
-            $('area.cytoBand').mousedown( function(e)
+            $('area.cytoBand').off('mousedown');  // Make sure this is only bound once
+            $('area.cytoBand').on("mousedown", function(e)
             {   // mousedown on chrom portion of image only (map items)
                 updateImgOffsets();
                 pxDown = e.clientX - img.scrolledLeft;
                 var pxY = e.clientY - img.scrolledTop;
                 if (mouseIsDown === false
                 && isWithin(chr.left,pxDown,chr.right) && isWithin(chr.top,pxY,chr.bottom)) {
                     mouseIsDown = true;
                     mouseHasMoved = false;
 
-                    $(document).bind('mousemove',chromMove);
-                    $(document).bind( 'mouseup', chromUp);
+                    $(document).on('mousemove',chromMove);
+                    $(document).on( 'mouseup', chromUp);
                     hiliteShow(pxDown,pxDown);
                     return false;
                 }
             });
         }
     }
 
     function chromMove(e)
     {   // If mouse was down, determine if dragged, then show hilite
         if ( mouseIsDown ) {
             var pxX = e.clientX - img.scrolledLeft;
             var relativeX = (pxX - pxDown);
             if (mouseHasMoved || (mouseHasMoved === false && Math.abs(relativeX) > 2)) {
                 mouseHasMoved = true;
                 if (isWithin(chr.left,pxX,chr.right))
                     hiliteShow(pxDown,pxX);
                 else if (pxX < chr.left)
                     hiliteShow(pxDown,chr.left);
                 else
                     hiliteShow(pxDown,chr.right);
             }
         }
     }
     function chromUp(e)
     {   // If mouse was down, handle final selection
-        $(document).unbind('mousemove',chromMove);
-        $(document).unbind('mouseup',chromUp);
+        $(document).off('mousemove',chromMove);
+        $(document).off('mouseup',chromUp);
         chromMove(e); // Just in case
         if (mouseIsDown) {
             updateImgOffsets();
             var bands;
             var pxUp = e.clientX - img.scrolledLeft;
             var pxY  = e.clientY - img.scrolledTop;
             if (isWithin(0,pxY,img.height)) {  // within vertical range or else cancel
                 var selRange = { beg: -1, end: -1, width: -1 };
                 var dontAsk = true;
 
                 if (e.ctrlKey) {
                     bands = findCytoBand(pxDown,pxUp);
                     if (bands.end > -1) {
                         pxDown = bands.left;
                         pxUp   = bands.right;
@@ -1539,31 +1539,31 @@
                 if (selRange.end > -1) {
                     // prompt, then submit for new position
                     selRange = rangeNormalizeToChrom(selRange,chr);
                     if (mouseHasMoved === false) { // Update highlight by converting bp back to pix
                         pxDown = convertFromBases(selRange.beg);
                         pxUp = convertFromBases(selRange.end);
                         hiliteShow(pxDown,pxUp);
                     }
                     //if ((selRange.end - selRange.beg) < 50000)
                     //    dontAsk = true;
                     if (dontAsk
                     || confirm("Jump to new position:\n\n"+chr.name+":"+commify(selRange.beg)+
                                "-"+commify(selRange.end)+" size:"+commify(selRange.width)) ) {
                         genomePos.setByCoordinates(chr.name, selRange.beg, selRange.end);
                         // Stop the presses :0)
-                        $('area.cytoBand').mousedown( function(e) { return false; });
+                        $('area.cytoBand').on("mousedown",  function(e) { return false; });
                         if (imageV2.backSupport) {
                             imageV2.navigateInPlace("position=" +  
                                     encodeURIComponent(genomePos.get().replace(/,/g,'')) + 
                                     "&findNearest=1",null,true);
                             hiliteCancel();
                         } else
                             document.TrackHeaderForm.submit();
                         return true; // Make sure the setTimeout below is not called.
                     }
                 }
             }
             hiliteCancel();
             setTimeout(posting.allowMapClicks,50);
         }
         mouseIsDown = false;
@@ -1789,52 +1789,52 @@
 
     // globals across all panImages
     portalWidth     = $(pan).width();
     portalAbsoluteX = $(pan).offset().left;
     // globals to one panImage
     var newX        = 0;
     var mouseDownX  = 0;
     var mouseIsDown = false;
     var beyondImage = false;
     var atEdge      = false;
 
     initialize();
 
     function initialize(){
 
-        $(pan).parents('td.tdData').mousemove(function(e) {
+        $(pan).parents('td.tdData').on("mousemove", function(e) {
             if (e.shiftKey)
                 $(this).css('cursor',"crosshair");  // shift-dragZoom
             else if ( theClient.isIePre11() )     // IE will override map item cursors if this gets set
                 $(this).css('cursor',"");  // normal pointer when not over clickable item
         });
 
         panAdjustHeight(prevX);
 
-        pan.mousedown(function(e){
+        pan.on("mousedown", function(e){
              if (e.which > 1 || e.button > 1 || e.shiftKey || e.metaKey || e.altKey || e.ctrlKey)
                  return true;
             if (mouseIsDown === false) {
                 if (rightClick.menu) {
                     rightClick.menu.hide();
                 }
                 mouseIsDown = true;
                 mouseDownX = e.clientX;
                 highlightAreas = $('.highlightItem');
                 atEdge = (!beyondImage && (prevX >= leftLimit || prevX <= rightLimit));
-                $(document).bind('mousemove',panner);
-                $(document).bind( 'mouseup', panMouseUp);  // Will exec only once
+                $(document).on('mousemove',panner);
+                $(document).on('mouseup', panMouseUp);  // Will exec only once
                 return false;
             }
         });
     }
 
     function panner(e) {
         //if (!e) e = window.event;
         if ( mouseIsDown ) {
             var relativeX = (e.clientX - mouseDownX);
 
             if (relativeX !== 0) {
                 if (posting.mapClicksAllowed()) {
                     // need to throw up a z-index div.  Wait mask?
                     savedPosition = genomePos.get();
                     dragMaskShow();
@@ -1872,32 +1872,32 @@
                     scrollHighlight(relativeX);
 
                 var nowPos = newX.toString() + "px";
                 $(".panImg").css( {'left': nowPos });
                 $('.tdData').css( {'backgroundPosition': nowPos } );
                 if (!only1xScrolling)
                     panAdjustHeight(newX);  // Will dynamically resize image while scrolling.
             }
         }
     }
     function panMouseUp(e) {  // Must be a separate function instead of pan.mouseup event.
         //if (!e) e = window.event;
         if (mouseIsDown) {
 
             dragMaskClear();
-            $(document).unbind('mousemove',panner);
-            $(document).unbind('mouseup',panMouseUp);
+            $(document).off('mousemove',panner);
+            $(document).off('mouseup',panMouseUp);
             mouseIsDown = false;
             // timeout incase the dragSelect.selectEnd was over a map item. select takes precedence.
             setTimeout(posting.allowMapClicks,50); 
 
             // Outside image?  Then abandon.
             var curY = e.pageY;
             var imgTbl = $('#imgTbl');
             var north = $(imgTbl).offset().top;
             var south = north + $(imgTbl).height();
             if (curY < north || curY > south) {
                 atEdge = false;
                 beyondImage = false;
                 if (savedPosition)
                     genomePos.set(savedPosition);
                 var oldPos = prevX.toString() + "px";
@@ -2188,31 +2188,31 @@
         var a = reg.exec(response);
         if (a && a[1]) {
             if ( ! window.open(a[1]) ) {
                 rightClick.windowOpenFailedMsg();
             }
             return;
         }
         warn("Couldn't parse out img src");
     },
 
     myPrompt: function (msg, callback)
     {   // replacement for prompt; avoids misleading/confusing security warnings which are caused
         // by prompt in IE 7+.   Callback is called if user presses "OK".
         $("body").append("<div id = 'myPrompt'><div id='dialog' title='Basic dialog'><form>" +
                             msg + "<input id='myPromptText' value=''></form>");
-        $('#myPromptText').bind('keypress', function(e) {
+        $('#myPromptText').on('keypress', function(e) {
             if (e.which === 13) {  // listens for return key
                 e.preventDefault();   // prevents return from also submitting whole form
                 $("#myPrompt").dialog("close");
                 callback($("#myPromptText").val());
             }
         });
         $("#myPrompt").dialog({
                                 modal: true,
                                 closeOnEscape: true,
                                 buttons: { "OK": function() {
                                                     var myPromptText = $("#myPromptText").val();
                                                     $(this).dialog("close");
                                                     callback(myPromptText);
                                                 }
                                         }
@@ -3136,31 +3136,31 @@
                 {
                 note = "<br><b>Needs zoom to &lt; "+maxSize/1000+" kbp.</b></small></span></li>";
                 htmlLines.push('<li><span style="color:grey">'+shortLabel+": <small>"+longLabel+note);
                 }
         }
         htmlLines.push("</ul>");
         content = htmlLines.join("");
             
         var title = hgTracks.chromName + ":" + (hgTracks.winStart+1) + "-" + hgTracks.winEnd;
         if (hgTracks.nonVirtPosition)
             title = hgTracks.nonVirtPosition;
         title += " on another website";
         $("body").append("<div id='extToolDialog' title='"+title+"'><p>" + content + "</p>");
 
 	// GALT 
-	$('a.extToolLink2').click(function(){$('#extToolDialog').dialog('close');});
+	$('a.extToolLink2').on("click", function(){$('#extToolDialog').dialog('close');});
 
         // copied from the hgTrackUi function below
         var popMaxHeight = ($(window).height() - 40);
         var popMaxWidth  = ($(window).width() - 40);
         var popWidth     = 600;
         if (popWidth > popMaxWidth)
             popWidth = popMaxWidth;
 
         // also copied from the hgTrackUi code below
         $('#extToolDialog').dialog({
             resizable: true,               // Let description scroll vertically
             height: popMaxHeight,
             width: popWidth,
             minHeight: 200,
             minWidth: 600,
@@ -3311,69 +3311,69 @@
 
             close: function() {
                 popUpHgt.cleanup();
             }
         });
         
     
         $('#hgTracksDialog').dialog('option' , 'title' , popUpHgt.title);
         $('#hgTracksDialog').dialog('open');
 
         // Initialize autocomplete for alt/fix sequence names
         autocompleteCat.init($('#singleAltHaploId'),
                              { baseUrl: 'hgSuggest?db=' + getDb() + '&type=altOrPatch&prefix=',
                                enterSelectsIdentical: true });
         // Make multi-region option inputs select their associated radio buttons
-        $('input[name="emPadding"]').keyup(function() {
+        $('input[name="emPadding"]').on("keyup", function() {
             $('#virtModeType[value="exonMostly"]').prop('checked', true); });
-        $('input[name="gmPadding"]').keyup(function() {
+        $('input[name="gmPadding"]').on("keyup", function() {
             $('#virtModeType[value="geneMostly"]').prop('checked', true); });
-        $('#multiRegionsBedInput').keyup(function() {
+        $('#multiRegionsBedInput').on("keyup", function() {
             $('#virtModeType[value="customUrl"]').prop('checked', true); });
-        $('#singleAltHaploId').keyup(function() {
+        $('#singleAltHaploId').on("keyup", function() {
             $('#virtModeType[value="singleAltHaplo"]').prop('checked', true); });
 
         // disable exit if not in MR mode
         if (!hgTracks.virtModeType) {
             $('#virtModeTypeDefaultLabel').addClass('disabled');
             $('#virtModeType[value="exonMostly"]').prop('checked', true);
             $('#virtModeType[value="default"]').prop('disabled', 'disabled');
         } else {
-            $('#virtModeType[value="default"]').removeAttr('disabled');
+            $('#virtModeType[value="default"]').prop('disabled', false);
         }
 
         // Customize message based on current mode
         var msg = "<em>Select a multi-region viewing mode below.</em>";  // default
         if (hgTracks.virtModeType) {
             msg = "The display is currently in <em><b> ";
             var mode = "unknown";
             if (hgTracks.virtModeType === "exonMostly") {
                 msg += "exon";
             } else if (hgTracks.virtModeType == "geneMostly") {
                 msg += "gene";
             } else if (hgTracks.virtModeType == "customUrl") {
                 msg += "custom regions";
             } else if (hgTracks.virtModeType == "singleAltHaplo") {
                 msg += "alt haplotype";
             } 
             msg += " </b></em> view. &nbsp;&nbsp;"
                 + "<em>Select a different viewing mode, or exit and return to normal view</em>.";
         }
         $('#multiRegionConfigStatusMsg').html(msg);
 
         // Make 'Cancel' button close dialog
-        $('input[name="Cancel"]').click(function() {
+        $('input[name="Cancel"]').on("click", function() {
             $('#hgTracksDialog').dialog('close');
         });
     }
 };
 
 var popUpHgcOrHgGene = {
 
     whichHgcMethod: "", // either hgc or hgGene or whatever else
     table: "", // the g= parameter
     title: "",
     saveAllVars: null, // when a click brings up hgTrackUi or something else with a form
     loadingId: null, // the id of the loading overlay
     href: "", // the link we're populating the pop up with
 
     cleanup: function ()
@@ -3568,31 +3568,31 @@
         //$('#hgcDialog').dialog('option' , 'title', titleText);
         $('#hgcDialog').dialog('open');
         document.addEventListener('click', e => {
             // if we clicked outside of the pop up, close the popup:
             mouseX = e.clientX;
             mouseY = e.clientY;
             popUpBox = document.getElementById("hgcDialog").parentElement.getBoundingClientRect();
             if (mouseX < popUpBox.left || mouseX > popUpBox.right ||
                     mouseY < popUpBox.top || mouseY > popUpBox.bottom) {
                 $("#hgcDialog").dialog("close");
             }
         });
 
         // Customize message based on current mode
         // Make 'Cancel' button close dialog
-        $('input[name="Cancel"]').click(function() {
+        $('input[name="Cancel"]').on("click", function() {
             $('#hgcDialog').dialog('close');
         });
     }
 };
 
 // Show the exported data hubs popup
 function showExportedDataHubsPopup() {
     let popUp = document.getElementById("exportedDataHubsPopup");
     title = popUp.title;
     if (title.length === 0 && popUp.getAttribute("mouseovertext") !== "") {title = popUp.getAttribute("mouseovertext");}
     $('#exportedDataHubsPopup').dialog({width:'650', title: title});
 }
 
 // Show the recommended track sets popup
 function showRecTrackSetsPopup() {
@@ -3611,31 +3611,31 @@
 function removeSessionPanel() {
     $('#recTrackSetsPanel').remove();
     setCartVar("hgS_otherUserSessionLabel", "off", null, false);
 }
 
 // A function to show the keyboard help dialog box, bound to ? and called from the menu bar
 function showHotkeyHelp() {
     $("#hotkeyHelp").dialog({width:'600'});
 }
 
 // A function to add an entry for the keyboard help dialog box to the menubar 
 // and add text that indicates the shortcuts to many static menubar items as suggested by good old IBM CUA/SAA
 function addKeyboardHelpEntries() {
     var html = '<li><a id="keybShorts" title="List all possible keyboard shortcuts" href="#">Keyboard Shortcuts</a><span class="shortcut">?</span></li>';
     $('#help .last').before(html);
-    $("#keybShorts").click( function(){showHotkeyHelp();} );
+    $("#keybShorts").on("click", function(){showHotkeyHelp();} );
 
     html = '<span class="shortcut">s s</span>';
     $('#sessionsMenuLink').after(html);
 
     html = '<span class="shortcut">p s</span>';
     $('#publicSessionsMenuLink').after(html);
 
     html = '<span class="shortcut">c t</span>';
     $('#customTracksMenuLink').after(html);
 
     html = '<span class="shortcut">t c</span>';
     $('#customCompositeMenuLink').after(html);
 
     html = '<span class="shortcut">t h</span>';
     $('#trackHubsMenuLink').after(html);
@@ -3958,31 +3958,31 @@
         if (popUp.trackDescriptionOnly) {
             var myWidth =  $(window).width() - 300;
             if (myWidth > 900)
                 myWidth = 900;
             $('#hgTrackUiDialog').dialog("option", "maxWidth", myWidth);
             $('#hgTrackUiDialog').dialog("option", "width", myWidth);
             $('#hgTrackUiDialog').dialog('option' , 'title' ,
                                hgTracks.trackDb[popUp.trackName].shortLabel+" Track Description");
             $('#hgTrackUiDialog').dialog('open');
         } else {
             $('#hgTrackUiDialog').dialog('option' , 'title' ,
                                   hgTracks.trackDb[popUp.trackName].shortLabel+" Track Settings");
             $('#hgTrackUiDialog').dialog('open');
         }
         var buttOk = $('button.ui-state-default');
-        $(buttOk).focus();
+        $(buttOk).trigger("focus");
     }
 };
 
   ///////////////////////////////
  //// imageV2  (aka imgTbl) ////
 ///////////////////////////////
 var imageV2 = {
 
     enabled:        false,  // Will be set to true unless advancedJavascriptFeatures
                             // is turned off OR if track search of config page
     imgTbl:         null,   // formerly "trackImgTbl"  The imgTbl or null if non-imageV2.
     inPlaceUpdate:  false,  // modified based on value of hgTracks.inPlaceUpdate & mapIsUpdateable
     mapIsUpdateable:true,
     lastTrack:      null,   // formerly (lastMapItem) this is used to try to keep what the
                             // last track the cursor passed.
@@ -4063,31 +4063,31 @@
                                         // Overwrite item's long value with symbol after the autocomplete plugin is done:
                                         window.setTimeout($('#positionInput').val(item.geneSymbol), 0);
                                     } else {
                                         selectedGene = item.value;
                                     }
                                     window.location.assign(item.id);
                                 } else {
                                     genomePos.set(item.id, getSizeFromCoordinates(item.id));
                                     if ($("#suggestTrack").length && $('#hgFindMatches').length) {
                                         // Set cart variables to open the hgSuggest gene track and highlight
                                         // the chosen transcript.  These variables will be submittted by the goButton
                                         // click handler.
                                         vis.makeTrackVisible($("#suggestTrack").val());
                                         cart.addVarsToQueue(["hgFind.matches"],[$('#hgFindMatches').val()]);
                                     }
-                                    $("#goButton").click();
+                                    $("#goButton").trigger("click");
                                 }
                             },
                             function (position) {
                                 genomePos.set(position, getSizeFromCoordinates(position));
                             }
                 );
             }
         }
     },
     
     afterImgChange: function (dirty)
     {   // Standard things to do when manipulations change image without ajax update.
         dragReorder.init();
         dragSelect.load(false);
         imageV2.drawHighlights();
@@ -4427,31 +4427,31 @@
                         hgTracks = newJson;
                         genomePos.original = undefined;
                         genomePos.setByCoordinates(hgTracks.chromName, hgTracks.winStart + 1, hgTracks.winEnd); // MOVED HERE GALT
                         initVars();
                         imageV2.afterReload();
                     }
                 } else {
                     warn("ASSERT: Attempt to update track without advanced javascript features.");
                 }
             }
             if (hgTracks.measureTiming) {
                 imageV2.updateTiming(response);
             }
         }
         if (this.disabledEle) {
-            this.disabledEle.removeAttr('disabled');
+            this.disabledEle.prop('disabled', false);
         }
         if (this.loadingId) {
             hideLoadingImage(this.loadingId);
         }
         jQuery('body').css('cursor', '');
         if (valid && this.currentId) {
             var top = $(document.getElementById("tr_" + this.currentId)).position().top;
             $(window).scrollTop(top - this.currentIdYOffset);
         }
     },
 
     loadRemoteTracks: function ()
     {
         if (hgTracks.trackDb) {
             for (var id in hgTracks.trackDb) {
@@ -4712,44 +4712,44 @@
         // contain data.  We save the position in the data and ajax update the image when the
         // back-button is pressed.  This works great for going back through ajax-updated position
         // changes, but is a bit messier when going back past a full-page retrieved state (as
         // described below).
     
         // NOTE: many things besides position could be ajax updated (e.g. track visibility). We are
         // using the back-button to keep track of position only.  Since the image should be updated
         // every-time the back button is pressed, all track settings should persist (not go back).
         // What will occasionally fail is vis box state and group expansion state. This is because
         // the back-button goes to a browser cached page and then the image alone is updated.
     
         imageV2.history = window.History;
         
         // The 'statechange' function triggerd by the back-button.
         // Whenever the position changes, then use ajax-update to refetch the position
-        imageV2.history.Adapter.bind(window,'statechange',function(){
+        imageV2.history.Adapter._bind(window, 'statechange',function(){
             var prevDbPos = imageV2.history.getState().data.lastDbPos;
             var prevPos = imageV2.history.getState().data.position;
             var curDbPos = hgTracks.lastDbPos;
             if (prevDbPos && prevDbPos !== curDbPos) {
                 // NOTE: this function is NOT called when backing past a full retrieval boundary
                 genomePos.set(decodeURIComponent(prevPos));
                 imageV2.navigateInPlace("" + prevDbPos, null, false);
             }
         });
         
         // With history support it is best that most position changes will ajax-update the image
         // This ensures that the 'go' and 'refresh' button will do so unless the chrom changes.
-        $("#goButton,input[value='refresh']").click(function () {
+        $("#goButton,input[value='refresh']").on("click", function () {
             var newPos = genomePos.get().replace(/,/g,'');
             if (newPos.length > 2000) {
                alert("Sorry, you cannot paste identifiers or sequences with more than 2000 characters into this box.");
                $('input[name="hgt.positionInput"]').val("");
                return false;
             }
 
             var newDbPos = hgTracks.lastDbPos;
             if ( ! imageV2.manyTracks() ) {
                 var newChrom = newPos.split(':')[0];
                 var oldChrom  = genomePos.getOriginalPos().split(':')[0];
                 if (newChrom === oldChrom) {
                     imageV2.markAsDirtyPage();
                     imageV2.navigateInPlace("position=" + encodeURIComponent(newPos), null, false);
                     window.scrollTo(0,0);
@@ -4971,32 +4971,32 @@
       }
       var validType = false;
       if (trackType) {
 	if (trackType.indexOf("wig") === 0) { validType = true; }
 	if (trackType.indexOf("bigWig") === 0) { validType = true; }
 	if (trackType.indexOf("wigMaf") === 0) { validType = false; }
 	if (hasChildren) { validType = false; }
       }
       if (! validType ) { return; }
       var tdData = "td_data_" + trackName;
       var tdDataId  = document.getElementById(tdData);
       var imgData = "img_data_" + trackName;
       var imgDataId  = document.getElementById(imgData);
       if (imgDataId && tdDataId) {
 	var url = mouseOver.jsonFileName(imgDataId);
-        $( tdDataId ).mousemove(mouseOver.mouseMoveDelay);
-        $( tdDataId ).mouseout(mouseOver.popUpDisappear);
+        $( tdDataId ).on("mousemove", mouseOver.mouseMoveDelay);
+        $( tdDataId ).on("mouseout", mouseOver.popUpDisappear);
         mouseOver.fetchJsonData(url);  // may be a refresh, don't know
       }
     },
 
     // given an X coordinate: x, find the index idx
     // in the rects[idx] array where rects[idx].x1 <= x < rects[idx].x2
     // returning -1 when not found
     // if we knew the array was sorted on x1 we could get out early
     //   when x < x1
     // Note, different track types could have different intersection
     //       procedures.  For example, the HiC track will need to intersect
     //       the mouse position within the diamond/square defined by the
     //       items in the display.
     findRange: function (x, rects)
     {
@@ -5215,58 +5215,58 @@
       mouseOver.items[trackName] = [];      // start array
       mouseOver.trackType[trackName] = arr[trackName].t;
       if (arr[trackName].hasOwnProperty('mo')) {
          mouseOver.mouseOverFunction[trackName] = arr[trackName].mo;
       } else {
          delete mouseOver.mouseOverFunction[trackName];
       }
       // add a 'mousemove' and 'mouseout' event listener to each track
       //     display object
       var tdData = "td_data_" + trackName;
       var tdDataId  = document.getElementById(tdData);
 // from jQuery doc:
 //  As the .mousemove() method is just a shorthand
 //    for .on( "mousemove", handler ), detaching is possible
 //      using .off( "mousemove" ).
-      $( tdDataId ).mousemove(mouseOver.mouseMoveDelay);
-      $( tdDataId ).mouseout(mouseOver.popUpDisappear);
+      $( tdDataId ).on("mousemove", mouseOver.mouseMoveDelay);
+      $( tdDataId ).on("mouseout", mouseOver.popUpDisappear);
       var itemCount = 0;	// just for monitoring purposes
       // save incoming x1,x2,v data into the mouseOver.items[trackName][] array
       var lengthLongestNumberString = 0;
       var longestNumber = 0;
       var hasMean = false;
       for (var datum in arr[trackName].d) {      // .d is the data array
          if (arr[trackName].d[datum].c > 1) { hasMean = true; }
          var lenV = arr[trackName].d[datum].v.toString().length;
          if (lenV > lengthLongestNumberString) {
 	   lengthLongestNumberString = lenV;
 	   longestNumber = arr[trackName].d[datum].v;
          }
         mouseOver.items[trackName].push(arr[trackName].d[datum]);
        ++itemCount;
       }
       mouseOver.tracks[trackName] = itemCount;	// != 0 -> indicates valid track
       var mouseOverValue = "";
       if (hasMean) {
          mouseOverValue = "&nbsp;~&nbsp;" + longestNumber + "&nbsp;";
       } else {
          mouseOverValue = "&nbsp;" + longestNumber + "&nbsp;";
       }
       if (mouseOver.mouseOverFunction[trackName] === "noAverage") {
          mouseOverValue = mouseOver.noAverageString;
       }
-      $('#mouseOverText').css('fontSize',mouseOver.browserTextSize);
+      $('#mouseOverText').css('fontSize',mouseOver.browserTextSize + "px");
       var maximumWidth = mouseOver.getWidthOfText(mouseOverValue);
       if ( 0 === mouseOver.noDataSize) {  // only need to do this once
         mouseOver.noDataSize = mouseOver.getWidthOfText(mouseOver.noDataString);
       }
       if (mouseOver.noDataSize > maximumWidth) {
           maximumWidth = mouseOver.noDataSize;
       }
       mouseOver.maximumWidth[trackName] = maximumWidth;
       }
     },  //      receiveData: function (arr)
 
     failedRequest: function(url)
     {   // failed request to get json data, remove it from the URL list
       if (mouseOver.jsonUrl[url]) {
         delete mouseOver.jsonUrl[url];
@@ -5333,55 +5333,55 @@
 
   //////////////////////
  //// track search ////
 //////////////////////
 var trackSearch = {
 
     searchKeydown: function (event)
     {
         if (event.which === 13) {
             // Required to fix problem on IE and Safari where value of hgt_tSearch is "-"
             //    (i.e. not "Search").
             // NOTE: must match TRACK_SEARCH_PAGER in hg/inc/searchTracks.h
             $("input[name=hgt_tsPage]").val(0);  
             $('#trackSearch').submit();
             // This doesn't work with IE or Safari.
-            // $('#searchSubmit').click();
+            // $('#searchSubmit').trigger("click");
         }
     },
 
     init: function ()
     {
         // Track search uses tabs
         if ($("#tabs").length > 0) {
             // Search page specific code
 
             var val = $('#currentTab').val();
             $("#tabs").tabs({
                                 show: function(event, ui) {
                                     $('#currentTab').val(ui.panel.id);
                                 },
                                 select: function(event, ui) { findTracks.switchTabs(ui); }
                             });
             $('#tabs').show();
             $("#tabs").tabs('option', 'selected', '#' + val);
             if (val === 'simpleTab' && $('div#found').length < 1) {
-                $('input#simpleSearch').focus();
+                $('input#simpleSearch').trigger("focus");
             }
             $("#tabs").css('font-family', jQuery('body').css('font-family'));
             $("#tabs").css('font-size', jQuery('body').css('font-size'));
-            $('.submitOnEnter').keydown(trackSearch.searchKeydown);
+            $('.submitOnEnter').on("keydown", trackSearch.searchKeydown);
             findTracks.normalize();
             findTracks.updateMdbHelp(0);
         }
     }
 };
 
 ////////
 // Download Current Tracks in window Dialog
 ////////
 var downloadCurrentTrackData = {
     downloadData: {}, // container for holding data while it comes in from the api
     currentRequests: {}, // pending requests
     intervalId: null, // the id of the timer that waits on the api
 
     failedTrackDataRequest: function(msg) {
@@ -5442,31 +5442,31 @@
                 if (fname.length === 0) {
                     fname = "trackDownload.txt";
                 }
                 switch (outType) {
                     case "tsv":
                         if (!fname.endsWith(".tsv")) {fname += ".tsv";}
                         break;
                     case "csv":
                         if (!fname.endsWith(".csv")) {fname += ".csv";}
                         break;
                     default:
                         if (!fname.endsWith(".txt")) {fname += ".txt";}
                         break;
                 }
                 anchor.download = fname;
-                anchor.click();
+                anchor.trigger("click");
                 window.URL.revokeObjectURL(anchor.href);
                 downloadCurrentTrackData.downloadData = {};
             }
         }
     },
 
     startDownload: function() {
         trackList = [];
         $(".downloadTrackName:checked").each(function(i, elem) {
             trackList.push(undecoratedTrack(elem.id));
         });
         chrom = hgTracks.chromName;
         start = hgTracks.winStart;
         end = hgTracks.winEnd;
         db = undecoratedDb(getDb());
@@ -5564,133 +5564,133 @@
                 htmlStr += "<br>";
             }
         });
         htmlStr += "<div ><label style='padding-right: 10px' for='downloadFileName'>Enter an output file name</label>";
         htmlStr += "<input type=text size=30 class='downloadFileName' id='downloadFileName'" +
             " value='" + getDb() + ".tracks'</input>";
         htmlStr += "<br>";
         htmlStr += "<label style='padding-right: 10px' for='outputFormat'>Choose an output format</label>";
         htmlStr += "<select name='outputFormat' id='outputFormat'>";
         htmlStr += "<option selected value='json'>JSON</option>";
         htmlStr += "<option value='csv'>CSV</option>";
         htmlStr += "<option value='tsv'>TSV</option>";
         htmlStr += "</select>";
         htmlStr += "</div>";
         downloadDialog.innerHTML = htmlStr;
-        $("#checkAllDownloadTracks").click( function() {
+        $("#checkAllDownloadTracks").on("click", function() {
             $(".downloadTrackName").each(function(i, elem) {
                 elem.checked = true;
             });
         });
-        $("#uncheckAllDownloadTracks").click( function() {
+        $("#uncheckAllDownloadTracks").on("click", function() {
             $(".downloadTrackName").each(function(i, elem) {
                 elem.checked = false;
             });
         });
         $(downloadDialog).dialog('open');
         $("[id$='Tooltip'").each(function(i, elem) {
             addMouseover(elem, "This track must be downloaded with the Table Browser");
         });
     }
 };
 
   ///////////////
  //// READY ////
 ///////////////
 $(document).ready(function()
 {
     imageV2.moveTiming();
 
     // hg.conf will turn this on 2020-10 - Hiram
     if (window.mouseOverEnabled) { mouseOver.addListener(); }
 
     // custom tracks get little trash icons
-    $("div.trackDeleteIcon").click( onTrackDelIconClick );
+    $("div.trackDeleteIcon").on("click", onTrackDelIconClick );
 
     // on Safari the back button doesn't call the ready function.  Reload the page if
     // the back button was pressed.
-    $(window).bind("pageshow", function(event) {
+    $(window).on("pageshow", function(event) {
         if (event.originalEvent.persisted) {
                 window.location.reload() ;
         }
     });
 
     // The page may be reached via browser history (back button)
     // If so, then this code should detect if the image has been changed via js/ajax
     // and will reload the image if necessary.
     // NOTE: this is needed for IE but other browsers can detect the dirty page much earlier
     if (!imageV2.backSupport) {
         if (imageV2.isDirtyPage()) {
             // mark as non dirty to avoid infinite loop in chrome.
             imageV2.markAsCleanPage();
             jQuery('body').css('cursor', 'wait');
             window.location = "../cgi-bin/hgTracks?hgsid=" + getHgsid();
             return false;
         }
     }
 
     initVars();
     imageV2.loadSuggestBox();
     if ($('#pdfLink').length === 1) {
-        $('#pdfLink').click(function(i) {
+        $('#pdfLink').on("click", function(i) {
             var thisForm = normed($('#TrackForm'));
             if (thisForm) {
                 //alert("posting form:"+$(thisForm).attr('name'));
                 updateOrMakeNamedVariable($(thisForm),'hgt.psOutput','on');
                 return postTheForm($(thisForm).attr('name'),this.href);
             }
             return true;
         });
     }
 
     if (imageV2.enabled) {
 
         // Make imgTbl allow drag reorder of imgTrack rows
         dragReorder.init();
         var imgTable = $(".tableWithDragAndDrop");
         if ($(imgTable).length > 0) {
             $(imgTable).tableDnD({
                 onDragClass: "trDrag",
                 dragHandle: "dragHandle",
                 scrollAmount: 40,
                 onDragStart: function(ev, table, row) {
                     mouse.saveOffset(ev);
-                    $(document).bind('mousemove',posting.blockTheMapOnMouseMove);
+                    $(document).on('mousemove',posting.blockTheMapOnMouseMove);
 
                     // Can drag a contiguous set of rows if dragging blue button
                     table.tableDnDConfig.dragObjects = [ row ]; // defaults to just the one
                     var btn = $( row ).find('p.btnBlue');  // btnBlue means cursor over left button
                     if (btn.length === 1) {
                         table.tableDnDConfig.dragObjects = dragReorder.getContiguousRowSet(row);
                         var compositeSet = dragReorder.getCompositeSet(row);
                         if (compositeSet && compositeSet.length > 0)
                             $( compositeSet ).find('p.btn').addClass('blueButtons');// blue persists
                     }
                 },
                 onDrop: function(table, row, dragStartIndex) {
                     var compositeSet = dragReorder.getCompositeSet(row);
                     if (compositeSet && compositeSet.length > 0)
                         $( compositeSet ).find('p.btn').removeClass('blueButtons');// blue persists
                     if ($(row).attr('rowIndex') !== dragStartIndex) {
                         // NOTE Even if dragging a contiguous set of rows,
                         // still only need to check the one under the cursor.
                         if (dragReorder.setOrder) {
                             dragReorder.setOrder(table);
                         }
                         dragReorder.zipButtons( table );
                     }
-                    $(document).unbind('mousemove',posting.blockTheMapOnMouseMove);
+                    $(document).off('mousemove',posting.blockTheMapOnMouseMove);
                     // Timeout necessary incase the onDrop over map item. onDrop takes precedence.
                     setTimeout(posting.allowMapClicks,100);
                 }
             });
         }
 
         // Drag scroll init
         if (hgTracks.imgBoxPortal) {
             // Turn on drag scrolling.
             $("div.scroller").panImages();
         }
 
         // Retrieve tracks via AJAX that may take too long to draw initialliy (i.e. a remote bigWig)
         var retrievables = $('#imgTbl').find("tr.mustRetrieve");
         if ($(retrievables).length > 0) {
@@ -5715,61 +5715,61 @@
             }
             let lsKey = "hgTracks_hideTutorial";
             let isUserLoggedIn = (typeof userLoggedIn !== 'undefined' && userLoggedIn === true);
             let hideTutorial = localStorage.getItem(lsKey);
             let tutMsgKey = "hgTracks_tutMsgCount";
             let tmp = localStorage.getItem(tutMsgKey), tutMsgCount = 0;
             if (tmp !== null) {tutMsgCount = parseInt(tmp);}
             // if the user is not logged in and they have not already gone through the
             // tutorial
             if (!isUserLoggedIn && !hideTutorial && tutMsgCount < 5) {
                 let msg = "A guided tutorial is available for new users: " +
                     "<button id='showTutorialLink' href=\"#showTutorial\">Start tutorial</button>";
                 notifBoxSetup("hgTracks", "hideTutorial", msg);
                 notifBoxShow("hgTracks", "hideTutorial");
                 localStorage.setItem("hgTracks_tutMsgCount", ++tutMsgCount);
-                $("#showTutorialLink").click(function() {
-                    $("#hgTracks_hideTutorialnotifyHide").click();
+                $("#showTutorialLink").on("click", function() {
+                    $("#hgTracks_hideTutorialnotifyHide").trigger("click");
                     tour.start();
                 });
             }
             // allow user to bring the tutorial up under the help menu whether they've seen
             // it or not
             let tutorialLinkMenuItem = document.createElement("li");
             tutorialLinkMenuItem.id = "hgTracksHelpTutorialMenuItem";
             tutorialLinkMenuItem.innerHTML = "<a id='hgTracksHelpTutorialLink' href='#showTutorial'>" +
                 "Interactive Tutorial</a>";
             $("#help > ul")[0].appendChild(tutorialLinkMenuItem);
-            $("#hgTracksHelpTutorialLink").click(function () {
+            $("#hgTracksHelpTutorialLink").on("click", function () {
                 tour.start();
             });
         }
         
         // Any highlighted region must be shown and warnBox must play nice with it.
         imageV2.drawHighlights();
         // When warnBox is dismissed, any image highlight needs to be redrawn.
-        $('#warnOK').click(function (e) { imageV2.drawHighlights();});
+        $('#warnOK').on("click", function (e) { imageV2.drawHighlights();});
         // Also extend the function that shows the warn box so that it too redraws the highlight.
         showWarnBox = (function (oldShowWarnBox) {
             function newShowWarnBox() {
                 oldShowWarnBox.apply();
                 imageV2.drawHighlights();
             }
             return newShowWarnBox;
         })(showWarnBox);
         // redraw highlights if the notification box is closed
-        $("[id$=notifyHide],[id$=notifyHideForever]").click(function(e) {
+        $("[id$=notifyHide],[id$=notifyHideForever]").on("click", function(e) {
             imageV2.drawHighlights();
         });
         notifBoxShow = (function(oldNotifBoxShow) {
             function newNotifBoxShow() {
                 oldNotifBoxShow.apply(null, arguments);
                 imageV2.drawHighlights();
             }
             return newNotifBoxShow;
         })(notifBoxShow);
     }
 
     // Drag select in chromIdeogram
     if ($('img#chrom').length === 1) {
         if ($('area.cytoBand').length >= 1) {
             $('img#chrom').chromDrag();
@@ -5803,31 +5803,31 @@
             this.onclick = posting.saveSettings;
         }
     });
 
 
     // add a 'link' to download the current track data (under hg.conf control)
     if (typeof showDownloadButton !== 'undefined' && showDownloadButton) {
         newListEl = document.createElement("li");
         newLink = document.createElement("a");
         newLink.setAttribute("id", "hgTracksDownload");
         newLink.setAttribute("name", "downloadTracks");
         newLink.textContent = "Download Current Track Data";
         newLink.href = "#";
         newListEl.appendChild(newLink);
         $("#downloads > ul")[0].appendChild(newListEl);
-        $("#hgTracksDownload").click(downloadCurrentTrackData.showDownloadUi);
+        $("#hgTracksDownload").on("click", downloadCurrentTrackData.showDownloadUi);
     }
 
     if (typeof showMouseovers !== 'undefined' && showMouseovers) {
         convertTitleTagsToMouseovers();
     }
 
 });
 
 function hgtWarnTiming(maxSeconds) {
     /* show a dialog box if the page load time was slower than x seconds. Has buttons to hide or never show this again. */
     var loadTime = window.performance.timing.domContentLoadedEventStart-window.performance.timing.navigationStart; /// in msecs
     var loadSeconds = loadTime/1000;
     if (loadSeconds < maxSeconds)
         return;