e0403e5eaf910cb8cbe1c9a1962bf36061dab8ef
larrym
  Mon Jul 25 12:14:11 2011 -0700
add some comments; more in place update changes (only live in larrym's tree)
diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index d3ae33e..54d6dd6 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -10,30 +10,43 @@
 var imgBoxPortal = false;
 var blockUseMap = false;
 var mapItems;
 var trackImg;               // jQuery element for the track image
 var trackImgTbl;            // jQuery element used for image table under imageV2
 var imgAreaSelect;          // jQuery element used for imgAreaSelect
 var originalImgTitle;
 var autoHideSetting = true; // Current state of imgAreaSelect autoHide setting
 var selectedMenuItem;       // currently choosen context menu item (via context menu).
 var browser;                // browser ("msie", "safari" etc.)
 var mapIsUpdateable = true;
 var currentMapItem;
 var floatingMenuItem;
 var visibilityStrsOrder = new Array("hide", "dense", "full", "pack", "squish");     // map browser numeric visibility codes to strings
 var supportZoomCodon = false;  // turn on experimental zoom-to-codon functionality (currently only on in larrym's tree).
+var inPlaceUpdate = false;     // modified based on value of hgTracks.inPlaceUpdate
+
+/* Data passed in from CGI via the hgTracks object:
+ * 
+ * string chromName           // current chromosome
+ * int winStart               // genomic start coordinate (0-based, half-open)
+ * int winEnd                 // genomic end coordinate
+ * int newWinWidth            // new width if user clicks on the top ruler (in bps)
+ * boolean dragSelection      // true if we should allow drag and select
+ * boolean revCmplDisp        // true if we are in reverse display
+ * int insideX                // width of side-bar (in pixels)
+ * int rulerClickHeight       // height of ruler (in pixels)
+ */
 
 function initVars(img)
 {
 // There are various entry points, so we call initVars in several places to make sure this variables get updated.
     if(!originalPosition) {
         // remember initial position and size so we can restore it if user cancels
         originalPosition = getOriginalPosition();
         originalSize = $('#size').text();
         originalCursor = jQuery('body').css('cursor');
     }
 }
 
 function selectStart(img, selection)
 {
     initVars();
@@ -162,66 +175,71 @@
 function selectionPixelsToBases(img, selection)
 // Convert selection x1/x2 coordinates to chromStart/chromEnd.
 {
 return pixelsToBases(img, selection.x1, selection.x2, hgTracks.winStart, hgTracks.winEnd);
 }
 
 function updatePosition(img, selection, singleClick)
 {
     var pos = pixelsToBases(img, selection.x1, selection.x2, hgTracks.winStart, hgTracks.winEnd);
     // 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;
     }
-    setPositionByCoordinates(hgTracks.chromName, pos.chromStart+1, pos.chromEnd);
-    return true;
+    var newPosition = setPositionByCoordinates(hgTracks.chromName, pos.chromStart+1, pos.chromEnd);
+    return newPosition;
 }
 
 function selectChange(img, selection)
 {
     initVars();
     if(selection.x1 != selection.x2) { // TODO: Larry could you examine this?
         if(checkPosition(img, selection)) {
             updatePosition(img, selection, false);
             jQuery('body').css('cursor', originalCursor);
         } else {
             jQuery('body').css('cursor', 'not-allowed');
         }
     }
     return true;
 }
 
 function selectEnd(img, selection)
 {
     var now = new Date();
     var doIt = false;
     if(originalCursor != null)
         jQuery('body').css('cursor', originalCursor);
     // ignore releases outside of the image rectangle (allowing a 10 pixel slop)
     if(autoHideSetting && checkPosition(img, selection)) {
        // ignore single clicks that aren't in the top of the image (this happens b/c the clickClipHeight test in selectStart
        // doesn't occur when the user single clicks).
-       doIt = startDragZoom != null || selection.y1 <= hgTracks.clickClipHeight;
+       doIt = startDragZoom != null || selection.y1 <= hgTracks.rulerClickHeight;
     }
     if(doIt) {
         // startDragZoom is null if mouse has never been moved
-	if(updatePosition(img, selection, (selection.x2 == selection.x1) || startDragZoom == null || (now.getTime() - startDragZoom) < 100)) {
+        newPosition = updatePosition(img, selection, (selection.x2 == selection.x1) || startDragZoom == null || (now.getTime() - startDragZoom) < 100);
+	if(newPosition != undefined) {
+            if(inPlaceUpdate) {
+                navigateInPlace("position=" + newPosition);
+            } else {
             jQuery('body').css('cursor', 'wait');
 	    document.TrackHeaderForm.submit();
 	}
+	}
     } else {
         setPosition(originalPosition, originalSize);
         originalPosition = originalSize = null;
 //        if(mapHtml) {
 //            $('#map').append(mapHtml);
 //        }
     }
 //    mapHtml = null;
     startDragZoom = null;
     setTimeout('blockUseMap=false;',50); // Necessary incase the selectEnd was over a map item. select takes precedence.
     return true;
 }
 
 $(window).load(function () {
     jQuery.each(jQuery.browser, function(i, val) {
@@ -233,50 +251,115 @@
     if(browser == "safari" && navigator.userAgent.indexOf("Chrome") != -1) {
         // Handle the fact that (as of 1.3.1), jQuery.browser reports "safari" when the browser is in fact Chrome.
         browser = "chrome";
     }
 
     // Safari has the following bug: if we update the hgTracks map dynamically, the browser ignores the changes (even
     // though if you look in the DOM the changes are there); so we have to do a full form submission when the
     // user changes visibility settings or track configuration.
     // As of 5.0.4 (7533.20.27) this is problem still exists in safari.
     // As of 5.1 (7534.50) this problem appears to have been fixed - unfortunately, logs for 7/2011 show vast majority of safari users 
     // are pre-5.1 (5.0.5 is by far the most common).
     //
     // Chrome used to have this problem too, but this  problem seems to have gone away as of
     // Chrome 5.0.335.1 (or possibly earlier).
     mapIsUpdateable = browser != "safari";
+    inPlaceUpdate = hgTracks.inPlaceUpdate && mapIsUpdateable;
     loadImgAreaSelect(true);
     if($('#hgTrackUiDialog'))
         $('#hgTrackUiDialog').hide();
 
     // Don't load contextMenu if jquery.contextmenu.js hasn't been loaded
     if(trackImg && jQuery.fn.contextMenu) {
         $('#hgTrackUiDialog').hide();
         if(imageV2) {
             $("map[name!=ideoMap]").each( function(t) { parseMap($(this,false));});
         } else {
             // XXXX still under debate whether we have to remove the map
             parseMap($('#map'),true);
             $('#map').empty();
         }
 
         originalImgTitle = trackImg.attr("title");
         if(imageV2) {
             loadContextMenu(trackImgTbl);
             //$(".trDraggable,.nodrop").each( function(t) { loadContextMenu($(this)); });
             // FIXME: why isn't rightClick for sideLabel working??? Probably because there is no link!
+            if(inPlaceUpdate) {
+                // Larry's experimental version of 1x panning (aka cheap panning).
+                var originalLeft;
+                var originalClientX;
+                var withinTrackImgTbl;
+                var last;
+                trackImgTbl.mousedown(
+                    function (e) {
+                        originalClientX = e.clientX;
+                        withinTrackImgTbl = true;
+                        last = new Date();
+                        jQuery('body').css('cursor', 'w-resize');
+                        $("img.dataImg").each( function(index, ele) {
+                                                   var left = $(ele).css('left');
+                                                   originalLeft = left.substring(0, left.length - 2)
+                                                   // we only need to look at one element, so bail out now.
+                                                   return false;
+                                               });
+                        jQuery(document).one('mouseup', function (e) {
+                                                 trackImgTbl.css('cursor', '');
+                                                 if(originalLeft != undefined) {
+                                                     if(withinTrackImgTbl && Math.abs(originalClientX - e.clientX) > 20) {
+                                                         originalLeft = undefined;
+                                                         var imgWidth = trackImgTbl.width() - hgTracks.insideX;
+                                                         var mult = (originalClientX - e.clientX) / imgWidth;
+                                                         var width = hgTracks.winEnd - hgTracks.winStart;
+                                                         hgTracks.winStart = hgTracks.winStart + Math.floor(width * mult);
+                                                         hgTracks.winEnd = hgTracks.winEnd + Math.floor(width * mult);
+                                                         setPositionByCoordinates(hgTracks.chromName, hgTracks.winStart + 1, hgTracks.winEnd)
+                                                         navigateInPlace("position=" + encodeURIComponent(hgTracks.chromName + ":" + (hgTracks.winStart + 1) + "-" + hgTracks.winEnd));
+                                                         // return true in case of ajax error.
+                                                         return true;
+                                                     } else {
+                                                         $("img.dataImg").each( function(index, ele) {
+                                                                                    $(ele).css( {'left': originalLeft + "px" });
+                                                                                });
+                                                         originalLeft = undefined;
+                                                         return true;
+                                                     }
+                                                 } else {
+                                                     return true;
+                                                 }
+                                             });
+                        return true;
+                    }
+                );
+                trackImgTbl.mouseenter(function(e) { withinTrackImgTbl = true; });
+                trackImgTbl.mouseleave(function(e) { withinTrackImgTbl = false; });
+                trackImgTbl.mousemove(
+                    function (e) {
+                        var now = new Date();
+                        // date logic is an attempt to fix IE related weirdness
+                        if(originalLeft != undefined && (now - last) > 100) {
+                            last = now;
+                            trackImgTbl.css('cursor', 'w-resize');
+                            $("img.dataImg").each( function(index, ele) {
+                                                       var newPos = originalLeft - (originalClientX - e.clientX) + "px";
+                                                       $(ele).css( {'left': newPos });
+                                                   });
+                        }
+                        return true;
+                    }
+                );
+            }
         } else {
             loadContextMenu(trackImg);
             trackImg.mousemove(
                 function (e) {
                     mapEvent(e);
                 }
             );
             trackImg.mousedown(
                 function (e) {
                     mapMouseDown(e);
                 }
             );
         }
     }
 });
@@ -2498,30 +2581,32 @@
                 if(!updateTrackImgForId(response, id)) {
                     showWarning("Couldn't parse out new image for id: " + id);
                     //alert("Couldn't parse out new image for id: " + id+"BR"+response);  // Very helpful
                 }
             }
             var json = scrapeVariable(response, "hgTracks");
             if(json != undefined) {
                 hgTracks.chromName = json.chromName;
                 hgTracks.winStart = json.winStart;
                 hgTracks.winEnd = json.winEnd;
                 $("input[name='c']").val(json.chromName);
                 $("input[name='l']").val(json.winStart);
                 $("input[name='r']").val(json.winEnd);
                 hgTracks.newWinWidth = json.newWinWidth;
                 setPositionByCoordinates(hgTracks.chromName, hgTracks.winStart + 1, hgTracks.winEnd);
+                originalPosition = undefined;
+                initVars();
             } else {
                 showWarning("Couldn't parse out new position info");
             }
             afterImgTblReload();
         } else {
             a= /<IMG([^>]+SRC[^>]+id='trackMap[^>]*)>/.exec(response);
             // Deal with a is null
             if(a[1]) {
                     var b = /WIDTH\s*=\s*['"]?(\d+)['"]?/.exec(a[1]);
                     var width = b[1];
                     b = /HEIGHT\s*=\s*['"]?(\d+)['"]?/.exec(a[1]);
                     var height = b[1];
                     b = /SRC\s*=\s*"([^")]+)"/.exec(a[1]);
                     var src = b[1];
                     $('#trackMap').attr('src', src);