de917aa7d6017e1f1bc5645b38e66669e9f5bf8a
larrym
  Mon Dec 12 09:49:01 2011 -0800
report accurate errors when errors are encountered when navigating in hgTracks (redmine #6229)
diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index e5a1573..0546cef 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -345,31 +345,41 @@
     blockUseMap: false,
 
     blockMapClicks:   function ()  {         posting.blockUseMap=true;  },
     allowMapClicks:   function ()  {         posting.blockUseMap=false; },
     mapClicksAllowed: function ()  { return (posting.blockUseMap == false); },
 
     blockTheMapOnMouseMove: function (ev)
     {
         if (!posting.blockUseMap && mouse.hasMoved(ev)) {
             posting.blockUseMap=true;
         }
     },
 
     mapClk: function ()
     {
+        // Use in-place update if the map item just modifies the current position (this is nice because it
+        // preserves the users current relative position).
+        var str = "/cgi-bin/hgTracks\\?position=([^:]+):(.+)&hgsid=(\\d+)$";
+        var reg = new RegExp(str);
+        var a = reg.exec(this.href);
+        if(a && a[1] && a[1] == hgTracks.chromName && imageV2.inPlaceUpdate) {
+            imageV2.navigateInPlace("position=" + encodeURIComponent(a[1] + ":" + a[2]), null, true);
+            return false;
+        } else {
         return posting.saveSettings(this);
+        }
     },
 
     saveSettings: function (obj)
     {
         if(posting.blockUseMap==true) {
             return false;
         }
         if(obj == undefined || obj.href == undefined) // called directly with obj
             obj = this;                               // and from callback without obj
 
         if ($(obj).hasClass('noLink'))  // TITLE_BUT_NO_LINK
             return false;
 
         if (obj.href.match('#') || obj.target.length > 0) {
             //alert("Matched # ["+obj.href+"] or has target:"+obj.target);
@@ -1752,30 +1762,36 @@
                     url += rightClick.selectedMenuItem.id;
             }
             location.assign(url);
 
         } else if (cmd == 'dragZoomMode') {
             dragSelect.autoHideSetting = true;
             var obj = dragSelect.areaSelector.data('imgAreaSelect');
             obj.setOptions({autoHide : true, movable: false});
         } else if (cmd == 'hilightMode') {
             dragSelect.autoHideSetting = false;
             var obj = dragSelect.areaSelector.data('imgAreaSelect');
             obj.setOptions({autoHide : false, movable: true});
         } else if (cmd == 'viewImg') {
             // Fetch a new copy of track img and show it to the user in another window. This code assume we have updated
             // remote cart with all relevant chages (e.g. drag-reorder).
+/* Here's how to do this more directly with hgRenderTracks:
+            if(window.open("../cgi-bin/hgRenderTracks?hgt.internal=1&hgsid=" + getHgsid()) == null) {
+                rightClick.windowOpenFailedMsg();
+            }
+            return;
+*/
             var data = "hgt.imageV1=1&hgt.trackImgOnly=1&hgsid=" + getHgsid();
             jQuery('body').css('cursor', 'wait');
             $.ajax({
                     type: "GET",
                     url: "../cgi-bin/hgTracks",
                     data: data,
                     dataType: "html",
                     trueSuccess: rightClick.handleViewImg,
                     success: catchErrorOrDispatch,
                     error: errorHandler,
                     cmd: cmd,
                     cache: false
                 });
         } else if (cmd == 'openLink' || cmd == 'followLink') {
             var href = rightClick.selectedMenuItem.href;
@@ -2577,53 +2593,59 @@
                     id: trackName,
                     newVisibility: newVisibility,
                     cache: false
                 });
     },
 
     updateImgAndMap: function (response, status)
     {   // Handle ajax response with an updated trackMap image, map and optional ideogram.
         //
         // this.cmd can be used to figure out which menu item triggered this.
         // this.id == appropriate track if we are retrieving just a single track.
 
         // update local hgTracks.trackDb to reflect possible side-effects of ajax request.
         var json = scrapeVariable(response, "hgTracks");
         var oldTrackDb = hgTracks.trackDb;
+        var valid = false;
         if(json == undefined) {
             showWarning("hgTracks object is missing from the response");
+        } else if (json.err) {
+            showWarning("Request failed; error: " + json.err);
         } else {
             if(this.id != null) {
                 if(json.trackDb[this.id]) {
                     var visibility = vis.enumOrder[json.trackDb[this.id].visibility];
                     var limitedVis;
                     if(json.trackDb[this.id].limitedVis)
                         limitedVis = vis.enumOrder[json.trackDb[this.id].limitedVis];
                     if(this.newVisibility && limitedVis && this.newVisibility != limitedVis)
                         // see redmine 1333#note-9
                         alert("There are too many items to display the track in " +
                                 this.newVisibility + " mode.");
                     var rec = hgTracks.trackDb[this.id];
                     rec.limitedVis = json.trackDb[this.id].limitedVis;
                     vis.update(this.id, visibility);
+                    valid = true;
                 } else {
                     showWarning("Invalid hgTracks.trackDb received from the server");
                 }
             } else {
+                valid = true;
                 hgTracks.trackDb = json.trackDb;
             }
         }
+        if(valid) {
         if(imageV2.enabled
         && this.id
         && this.cmd
         && this.cmd != 'wholeImage'
         && this.cmd != 'selectWholeGene') {
             // Extract <TR id='tr_ID'>...</TR> and update appropriate row in imgTbl;
             // this updates src in img_left_ID, img_center_ID and img_data_ID and map in map_data_ID
             var id = this.id;
             if(imageV2.updateImgForId(response, id)) {
                 imageV2.afterReload();
             } else {
                 showWarning("Couldn't parse out new image for id: " + id);
                 //alert("Couldn't parse out new image for id: " + id+"BR"+response);  // Very helpful
             }
         } else {
@@ -2672,38 +2694,39 @@
             //    showWarning("Couldn't parse out map");
         }
         // Parse out new ideoGram url (if available)
         // e.g.: <IMG SRC = "../trash/hgtIdeo/hgtIdeo_hgwdev_larrym_61d1_8b4a80.gif" BORDER=1 WIDTH=1039 HEIGHT=21 USEMAP=#ideoMap id='chrom'>
         // We do this last b/c it's least important.
         var a = /<IMG([^>]+SRC[^>]+id='chrom'[^>]*)>/.exec(response);
         if(a && a[1]) {
             var b = /SRC\s*=\s*"([^")]+)"/.exec(a[1]);
             if(b && b[1]) {
                 $('#chrom').attr('src', b[1]);
             }
         }
         if(hgTracks.measureTiming) {
             imageV2.updateTiming(response);
         }
+        }
         if(this.disabledEle) {
             this.disabledEle.removeAttr('disabled');
         }
         if(this.loadingId) {
             hideLoadingImage(this.loadingId);
         }
         jQuery('body').css('cursor', '');
-        if(this.currentId) {
+        if(valid && this.currentId) {
             var top = $(document.getElementById("tr_" + this.currentId)).position().top;
             $(window).scrollTop(top - this.currentIdYOffset);
         }
     },
 
     loadRemoteTracks: function ()
     {
         if(typeof(hgTracks.trackDb) != "undefined" && hgTracks.trackDb != null) {
             for (var id in hgTracks.trackDb) {
                 var rec = hgTracks.trackDb[id];
                 if(rec.type == "remote") {
                     if($("#img_data_" + id).length > 0) {
                         // load the remote track renderer via jsonp
                         rec.loadingId = showLoadingImage("tr_" + id);
                         var script = document.createElement('script');