2542ace0d7aa8b198d7de360b21edd3ce88364d6
galt
  Fri Jan 29 19:19:18 2016 -0800
A request was made to hide the chromIdeo when we are in custom multi-region mode
and ther is more than two or more different chroms in the region list.
This is kind of a compromise. It avoids the seeming asserting that there is just
one chrom in the view.  But we also lose our place-holder that shows
the multi-region mode that one is in.  When a user zooms in far enough
that the screen only has 1 window from 1 region, then the chromIdeo for that single
chrom needs to be updated. So I have added a small change where when the
ideo is hidden we still include an empty hidden map and chromIdeo image html.
So that hgTracks.js::updateChromImg can update it later at runtime with ajax callbacks.
This is also a partial step towards supporting multiple chromIdeos someday.

Squashed commit of the following:

commit 764c2932d6be67d6a67b3df47b8cf44f3c5239e4
Author: Galt Barber <galt@soe.ucsc.edu>
Date:   Fri Jan 29 19:11:53 2016 -0800

code cleanup

commit 408ee8dadde6d7948740a65e0a298ad006470ab7
Author: Galt Barber <galt@soe.ucsc.edu>
Date:   Fri Jan 29 18:37:47 2016 -0800

checkin of fix for more dynamic ideogram

commit ccac0a2f112dabd6e798904bd57b0cb5fe7c0a22
Author: Galt Barber <galt@soe.ucsc.edu>
Date:   Thu Jan 28 11:29:33 2016 -0800

initial probing towards a solution for having dynmaic chromIdeos, a step on the way to supporting mulitple chromIdeos

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index bee1e8d..7513667 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -622,55 +622,62 @@
 boolean doIdeo = TRUE;
 int ideoWidth = round(.8 *tl.picWidth);
 int ideoHeight = 0;
 int textWidth = 0;
 struct tempName pngTn;
 boolean nukeIdeoFromList = FALSE;
 if (ideoTn == NULL)
     ideoTn = &pngTn;   // not returning value
 
 ideoTrack = chromIdeoTrack(*pTrackList);
 
 //warn("makeChromIdeoImage ideoTrack=%lu ideoTrack->track=%s", (unsigned long) ideoTrack, ideoTrack ? ideoTrack->track : ""); // DEBUG REMOVE
 
 /* If no ideogram don't draw. */
 if(ideoTrack == NULL)
+    {
     doIdeo = FALSE;
+    }
 else if(trackImgOnly && !ideogramToo)
     {
     doIdeo = FALSE;
     }
 else
     {
     //warn("makeChromIdeoImage about to remove track from group and tracklist"); // DEBUG REMOVE
     /* Remove the track from the group and track list. */
     removeTrackFromGroup(ideoTrack);
     slRemoveEl(pTrackList, ideoTrack);
     nukeIdeoFromList = TRUE;
 
     /* Fix for hide all button hiding the ideogram as well. */
     if(withIdeogram && ideoTrack->items == NULL)
 	{
 	ideoTrack->visibility = tvDense;
 	ideoTrack->loadItems(ideoTrack);
 	}
     limitVisibility(ideoTrack);
 
     /* If hidden don't draw. */
     if(ideoTrack->limitedVis == tvHide || !withIdeogram)
         doIdeo = FALSE;
     }
+// TODO use DIV in future (can update entire div at once in hgTracks.js)
+//hPrintf("<DIV id='chromIdeoDiv'>\n"); 
+// FYI from testing, I see that there is code that inserts warning error messages
+//  right before ideoMap, so any changes to that name or adding the DIV would require
+//  updating the warning-insertion target name.
 if(doIdeo)
     {
     //warn("makeChromIdeoImage doIdeo = TRUE"); // DEBUG REMOVE
     char startBand[16];
     char endBand[16];
     char title[64];  // was 32
     startBand[0] = endBand[0] = '\0';
     fillInStartEndBands(ideoTrack, startBand, endBand, sizeof(startBand));
     /* Start up client side map. */
     if (!psOutput)
         hPrintf("<MAP Name=%s>\n", mapName);
     /* Draw the ideogram. */
     ideoHeight = gfxBorder + ideoTrack->height;
     if (psOutput)
         {
@@ -708,41 +715,58 @@
     int saveInsideX = insideX;
     int saveInsideWidth = insideWidth;
     insideX = textWidth+4;
     insideWidth = ideoWidth-insideX;
     ideoTrack->drawItems(ideoTrack, winStart, winEnd, hvg, insideX, gfxBorder,
                          insideWidth, font, ideoTrack->ixColor, ideoTrack->limitedVis);
     insideX = saveInsideX;
     insideWidth = saveInsideWidth;
     hvGfxUnclip(hvg);
     /* Save out picture and tell html file about it. */
     hvGfxClose(&hvg);
     /* Finish map. */
     if (!psOutput)
         hPrintf("</MAP>\n");
     }
+
+// create an empty hidden-map place holder which can change dynamically with ajax callbacks.
+if (!doIdeo && !psOutput) 
+    {
+    hPrintf("<MAP Name=%s>\n", mapName);
+    hPrintf("</MAP>\n");
+    }
+
 hPrintf("<TABLE BORDER=0 CELLPADDING=0>");
-if (doIdeo && !psOutput)
+if (!psOutput)
+    {
+    // by default, create an empty hidden ideo place holder for future dynamic ajax update
+    char *srcPath = "";
+    char *style = "display: none;";
+    if (doIdeo)
 	{
+	srcPath = ideoTn->forHtml;
+	style = "display: inline;";
+	}
     hPrintf("<TR><TD HEIGHT=5></TD></TR>");
-    hPrintf("<TR><TD><IMG SRC = \"%s\" BORDER=1 WIDTH=%d HEIGHT=%d USEMAP=#%s id='chrom'>",
-            ideoTn->forHtml, ideoWidth, ideoHeight, mapName);
+    hPrintf("<TR><TD><IMG SRC = \"%s\" BORDER=1 WIDTH=%d HEIGHT=%d USEMAP=#%s id='chrom' style='%s'>",
+            srcPath, ideoWidth, ideoHeight, mapName, style);
     hPrintf("</TD></TR>");
     hPrintf("<TR><TD HEIGHT=5></TD></TR></TABLE>\n");
     }
 else
     hPrintf("<TR><TD HEIGHT=10></TD></TR></TABLE>\n");
+//hPrintf("</DIV>\n");  // TODO use DIV in future
 if(ideoTrack != NULL)
     {
     ideoTrack->limitedVisSet = TRUE;
     ideoTrack->limitedVis = tvHide; /* Don't draw in main gif. */
     }
 return nukeIdeoFromList;
 }
 
 char *pcrResultMapItemName(struct track *tg, void *item)
 /* Stitch accession and display name back together (if necessary). */
 {
 struct linkedFeatures *lf = item;
 return pcrResultItemAccName(lf->name, lf->extra);
 }
 
@@ -7223,30 +7247,41 @@
 if (emGeneTable)
     {
     struct track *myTrackList = getTrackListForOneTrack(emGeneTable);
     emGeneTrack = rFindTrackWithTable(emGeneTable, myTrackList);
     }
 if (!emGeneTable || !emGeneTrack) 
     {
     cartRemove(cart, "emGeneTable");
     // It is preferable not to create a complete track list early on,
     //  but now we need one to find the best default emGeneTable and track.
     initTrackList(); 
     findBestEMGeneTable(trackList);
     }
 }
 
+boolean windowsHaveMultipleChroms()
+/* Are there multiple different chromosomes in the windows list? */
+{
+struct window *window;
+for (window=windows->next; window; window=window->next)
+    {
+    if (!sameString(window->chromName,windows->chromName))
+	return TRUE;
+    }
+return FALSE;
+}
 
 void doTrackForm(char *psOutput, struct tempName *ideoTn)
 /* Make the tracks display form with the zoom/scroll buttons and the active
  * image.  If the ideoTn parameter is not NULL, it is filled in if the
  * ideogram is created.  */
 {
 struct group *group;
 struct track *track;
 char *freezeName = NULL;
 boolean hideAll = cgiVarExists("hgt.hideAll");
 boolean defaultTracks = cgiVarExists("hgt.reset");
 boolean showedRuler = FALSE;
 boolean showTrackControls = cartUsualBoolean(cart, "trackControlsOnMain", TRUE);
 long thisTime = 0, lastTime = 0;
 
@@ -7673,43 +7708,48 @@
 	}
     slReverse(&jsonForList->val.jeList);
     jsonObjectAdd(jsonForClient, "windowsAfter", jsonForList);
 
     jsonForList = newJsonList(NULL);
     // also store js nonVirtPosition
     jsonObjectAdd(jsonForClient, "nonVirtPosition", newJsonString(cartString(cart, "nonVirtPosition")));
     jsonObjectAdd(jsonForClient, "virtChromChanged", newJsonBoolean(virtChromChanged));
     jsonObjectAdd(jsonForClient, "virtualSingleChrom", newJsonBoolean(virtualSingleChrom())); // DISGUISE POS
     }
 
 char dbPosKey[256];
 safef(dbPosKey, sizeof(dbPosKey), "position.%s", database);
 jsonObjectAdd(jsonForClient, "lastDbPos", newJsonString(cartString(cart, dbPosKey)));
 
-
-
-if(trackImgOnly && !ideogramToo)
+// hide chromIdeo
+if ((trackImgOnly && !ideogramToo) 
+|| (sameString(virtModeType, "customUrl") && windowsHaveMultipleChroms()) // Special case hide by request
+)
     {
     for(window=windows;window;window=window->next)
 	{
 	struct track *ideoTrack = chromIdeoTrack(window->trackList);
 	if (ideoTrack)
 	    {
 	    ideoTrack->limitedVisSet = TRUE;
 	    ideoTrack->limitedVis = tvHide; /* Don't draw in main gif. */
 	    }
 	}
+    }
+
+if (trackImgOnly && !ideogramToo) 
+    {
     makeActiveImage(trackList, psOutput);
     fflush(stdout);
     return;  // bail out b/c we are done
     }
 
 if (!hideControls)
     {
     /* set white-space to nowrap to prevent buttons from wrapping when screen is
      * narrow */
     hPrintf("<DIV STYLE=\"white-space:nowrap;\">\n");
     printMenuBar();
     //menuBarAppendExtTools();
 
     /* Show title . */
     freezeName = hFreezeFromDb(database);