Index: src/hg/hgTracks/hgTracks.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/hgTracks/hgTracks.c,v
retrieving revision 1.1640
retrieving revision 1.1641
diff -b -B -U 4 -r1.1640 -r1.1641
--- src/hg/hgTracks/hgTracks.c	9 Apr 2010 20:06:45 -0000	1.1640
+++ src/hg/hgTracks/hgTracks.c	10 Apr 2010 01:14:56 -0000	1.1641
@@ -1793,8 +1793,27 @@
 hvGfxUnclip(hvg);
 return y;
 }
 
+static void rAddToTrackHash(struct hash *trackHash, struct track *trackList)
+/* Add list and any children of list to hash. */
+{
+struct track *track;
+for (track = trackList; track != NULL; track = track->next)
+    {
+    hashAddUnique(trackHash, track->mapName, track);
+    rAddToTrackHash(trackHash, track->subtracks);
+    }
+}
+
+static void makeGlobalTrackHash(struct track *trackList)
+/* Start a global track hash. */
+{
+trackHash = newHash(8);
+rAddToTrackHash(trackHash, trackList);
+}
+
+
 void makeActiveImage(struct track *trackList, char *psOutput)
 /* Make image and image map. */
 {
 struct track *track;
@@ -1823,10 +1842,8 @@
 boolean rulerCds = zoomedToCdsColorLevel;
 int rulerClickHeight = 0;
 int newWinWidth = 0;
 
-/* Start a global track hash. */
-trackHash = newHash(8);
 /* Figure out dimensions and allocate drawing space. */
 pixWidth = tl.picWidth;
 
 leftLabelX = gfxBorder;
@@ -1929,9 +1946,8 @@
 #define maxSafeHeight   32000
 /* Hash tracks/subtracks, limit visibility and calculate total image height: */
 for (track = trackList; track != NULL; track = track->next)
     {
-    hashAddUnique(trackHash, track->mapName, track);
     limitVisibility(track);
     if (!safeHeight)
         {
         track->limitedVis = tvHide;
@@ -1945,9 +1961,8 @@
             struct track *subtrack;
             for (subtrack = track->subtracks; subtrack != NULL;
                          subtrack = subtrack->next)
                 {
-                hashAddUnique(trackHash, subtrack->mapName, subtrack);
                 if (!isSubtrackVisible(subtrack))
                     continue;
                 if (!subtrack->limitedVisSet)
                     {
@@ -3182,9 +3197,9 @@
 #endif//def USE_BAM
 else if (sameString(type, "makeItems"))
     {
     tg = trackFromTrackDb(tdb);
-    makeItemsMethodsCt(tg);
+    makeItemsMethods(tg);
     tg->nextItemButtonable = TRUE;
     tg->customPt = ct;
     }
 else
@@ -4182,8 +4197,18 @@
 hPrintf( "}\n");
 hPrintf("</script>\n");
 }
 
+void jsCommandDispatch(char *command, struct track *trackList)
+/* Dispatch a command sent to us from some javaScript event.  
+ * This gets executed after the track list is built, but before
+ * the track->loadItems methods are called.  */
+{
+uglyf("jsCommandDispatch(%s) on %d tracks<BR>\n", command, slCount(trackList));
+if (startsWithWord("makeItems", command))
+    makeItemsJsCommand(command, trackList, trackHash);
+}
+
 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.  */
@@ -4235,8 +4260,9 @@
     hideControls = cartUsualBoolean(cart, "hideControls", FALSE);
 if (measureTiming)
     uglyTime("Time before getTrackList");
 trackList = getTrackList(&groupList, defaultTracks ? -1 : -2);
+makeGlobalTrackHash(trackList);
 #ifdef SOON
 if (measureTiming)
     uglyTime("getTrackList");
 #endif /* SOON */
@@ -4285,9 +4311,9 @@
 char *jsCommand = cartCgiUsualString(cart, hgtJsCommand, "");
 if (!isEmpty(jsCommand))
    {
    cartRemove(cart, hgtJsCommand);
-   uglyf("Hello javascript world! Your command is '%s'<BR>\n ", jsCommand);
+   jsCommandDispatch(jsCommand, trackList);
    }
 
 /* Tell tracks to load their items. */
 for (track = trackList; track != NULL; track = track->next)

