891063b37aee1aaa86ad2eb4af5e389c6f9220bb
larrym
  Wed Nov 17 15:08:53 2010 -0800
handle case where track cannot be changed to higher visibility; refactor code into updateVisibility
diff --git src/hg/js/hgTracks.js src/hg/js/hgTracks.js
index 62ea39e..32b57a2 100644
--- src/hg/js/hgTracks.js
+++ src/hg/js/hgTracks.js
@@ -12,30 +12,31 @@
 var startDragZoom = null;
 var newWinWidth;
 var imageV2 = false;
 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 visibilityStrsOrder = new Array("hide", "dense", "full", "pack", "squish");     // map browser numeric visibility codes to strings
 
 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();
@@ -1635,38 +1636,31 @@
             // make sure the link contains chrom info (necessary b/c we are stripping hgsid)
             href = href + "&c=" + chrom;
         }
         if(window.open(href) == null) {
             windowOpenFailedMsg();
         }
     } else if (cmd == 'followLink') {
         // XXXX This is blocked by Safari's popup blocker (without any warning message).
         location.assign(selectedMenuItem.href);
     } else {   // if( cmd in 'hide','dense','squish','pack','full','show' )
         // Change visibility settings:
         //
         // First change the select on our form:
         var id = selectedMenuItem.id;
         var rec = trackDbJson[id];
-        var selectUpdated = false;
-        $("select[name=" + id + "]").each(function(t) {
-            $(this).val(cmd);
-            selectUpdated = true;
-        });
-        if(rec) {
-            rec.localVisibility = cmd;
-        }
+        var selectUpdated = updateVisibility(id, cmd);
 
         // Now change the track image
         if(imageV2 && cmd == 'hide')
         {
             // Hide local display of this track and update server side cart.
             // Subtracks controlled by 2 settings so del vis and set sel=0.  Others, just set vis hide.
             if(rec.parentTrack != undefined)
                 setCartVars( [ id, id+"_sel" ], [ "[]", 0 ] ); // Don't set '_sel" to [] because default gets used, but we are explicitly hiding this!
             else
                 setCartVar(id, 'hide' );
             $('#tr_' + id).remove();
             initImgTblButtons();
             loadImgAreaSelect(false);
         } else if (!mapIsUpdateable) {
             jQuery('body').css('cursor', 'wait');
@@ -1686,30 +1680,31 @@
             }
             //var center = $("#img_data_" + id);
             //center.attr('src', "../images/loading.gif")
             //center.attr('style', "text-align: center; display: block;");
             //warn("hgTracks?"+data); // Uesful to cut and paste the url
             var loadingId = showLoadingImage("tr_" + id);
             $.ajax({
                        type: "GET",
                        url: "../cgi-bin/hgTracks",
                        data: data,
                        dataType: "html",
                        trueSuccess: handleUpdateTrackMap,
                        success: catchErrorOrDispatch,
                        error: errorHandler,
                        cmd: cmd,
+                       newVisibility: cmd,
                        id: id,
                        loadingId: loadingId,
                        cache: false
                    });
         }
     }
 }
 
 function makeContextMenuHitCallback(title)
 {
 // stub to avoid problem with a function closure w/n a loop
     return function(menuItemClicked, menuObject) {
         contextMenuHit(menuItemClicked, menuObject, title); return true;
     };
 }
@@ -1745,31 +1740,30 @@
                 if(cur) {
                     select.children().each(function(index, o) {
                                                var title = $(this).val();
                                                var str = title;
                                                if(title == cur) {
                                                    str += selectedImg;
                                                }
                                                var o = new Object();
                                                o[str] = {onclick: function (menuItemClicked, menuObject) { contextMenuHit(menuItemClicked, menuObject, title); return true;}};
                                                menu.push(o);
                                            });
                     done = true;
                 } else {
                     if(rec) {
                         // XXXX check current state from a hidden variable.
-                        var visibilityStrsOrder = new Array("hide", "dense", "full", "pack", "squish");
                         var visibilityStrs = new Array("hide", "dense", "squish", "pack", "full");
                         for (i in visibilityStrs) {
                             // XXXX use maxVisibility and change hgTracks so it can hide subtracks
                             var o = new Object();
                             var str = visibilityStrs[i];
                             if(rec.canPack || (str != "pack" && str != "squish")) {
                                 if(rec.localVisibility) {
                                     if(rec.localVisibility == str) {
                                         str += selectedImg;
                                     }
                                 } else if(str == visibilityStrsOrder[rec.visibility]) {
                                     str += selectedImg;
                                 }
                                 o[str] = {onclick: makeContextMenuHitCallback(visibilityStrs[i])};
                                 menu.push(o);
@@ -1959,36 +1953,31 @@
     var newVis = changedVars[trackName];
     var hide = (newVis != null && (newVis == 'hide' || newVis == '[]'));  // subtracks do not have "hide", thus '[]'
     if($('#imgTbl') == undefined) { // On findTracks or config page
         setVarsFromHash(changedVars);
         //if(hide) // TODO: When findTracks or config page has cfg popup, then vis change needs to be handled in page here
     }
     else {  // On image page
         if(hide) {
             setVarsFromHash(changedVars);
             $('#tr_' + trackName).remove();
             initImgTblButtons();
             loadImgAreaSelect(false);
         } else {
             // Keep local state in sync if user changed visibility
             if(newVis != null) {
-                $("select[name=" + trackName + "]").each(function(t) {
-                    $(this).val(newVis);
-                });
-                if(rec) {
-                    rec.localVisibility = newVis;
-                }
+                updateVisibility(trackName, newVis);
             }
             var urlData = varHashToQueryString(changedVars);
             if(mapIsUpdateable) {
                 updateTrackImg(trackName,urlData,"");
             } else {
                 window.location = "../cgi-bin/hgTracks?" + urlData + "&hgsid=" + getHgsid();
             }
         }
     }
 }
 
 function handleTrackUi(response, status)
 {
 // Take html from hgTrackUi and put it up as a modal dialog.
     if(popUpTrackDescriptionOnly) {
@@ -2045,30 +2034,44 @@
 function handleUpdateTrackMap(response, status)
 {
 // Handle ajax response with an updated trackMap image (gif or png) and map.
 //
 // this.cmd can be used to figure out which menu item triggered this.
 //
 // e.g.: <IMG SRC = "../trash/hgtIdeo/hgtIdeo_hgwdev_larrym_61d1_8b4a80.gif" BORDER=1 WIDTH=1039 HEIGHT=21 USEMAP=#ideoMap id='chrom'>
     // Parse out new ideoGram url (if available)
     var a = /<IMG([^>]+SRC[^>]+id='chrom'[^>]*)>/.exec(response);
     if(a && a[1]) {
         b = /SRC\s*=\s*"([^")]+)"/.exec(a[1]);
         if(b[1]) {
             $('#chrom').attr('src', b[1]);
         }
     }
+    if(this.newVisibility) {
+        var re = /<\!-- trackDbJson -->\n<script>var trackDbJson = ([\S\s]+)<\/script><\!-- trackDbJson -->/m;
+        a = re.exec(response);
+        if(a && a[1]) {
+            var json = eval("(" + a[1] + ")");
+            var visibility = visibilityStrsOrder[json[this.id].visibility];
+            if(this.newVisibility != visibility) {
+                alert("Unable to change visibility to " + this.newVisibility + ".\n\nThis occurs when there are too many items to display the track in " + this.newVisibility + " mode.");
+                updateVisibility(this.id, visibility);
+            }
+        } else {
+            alert("trackDbJson is missing from the response");
+        }
+    }
     if(imageV2 && 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(this.loadingId) {
 	          hideLoadingImage(this.loadingId);
           }
           var rec = trackDbJson[id];
           var str = "<TR id='tr_" + id + "'[^>]*>([\\s\\S]+?)</TR>";
           var reg = new RegExp(str);
           a = reg.exec(response);
           if(a && a[1]) {
 //               $('#tr_' + id).html();
 //               $('#tr_' + id).empty();
                $('#tr_' + id).html(a[1]);
@@ -2514,15 +2517,31 @@
                 if(typeof(disabled[val]) == 'undefined')
                     span.html("<a target='_blank' title='detailed descriptions of terms' href='" + str + "'>" + text + "</a>");
                 else
                     span.empty();
             }
         } else {
             return;
         }
     }
 }
 
 function windowOpenFailedMsg()
 {
     alert("Your web browser prevented us from opening a new window.\n\nYou need to change your browser settings to allow popups from " + document.domain);
 }
+
+function updateVisibility(track, visibility)
+{
+// Updates visibility state in trackDbJson and any visible elements on the page.    
+// returns true if we modify at least one select in the group list
+    var rec = trackDbJson[track];
+    var selectUpdated = false;
+    $("select[name=" + track + "]").each(function(t) {
+                                          $(this).val(visibility);
+                                          selectUpdated = true;
+                                      });
+    if(rec) {
+        rec.localVisibility = visibility;
+    }
+    return selectUpdated;
+}