a1707797e434bd59ef53ef18510c62eb8cb100cb
larrym
  Fri Mar 23 13:32:01 2012 -0700
commit tim's code to stop using trackHash in compositeMetadataToggle; this fixes #7376
diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index 76141b9..87fe8dd 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -47,85 +47,71 @@
 #ifdef BUTTONS_BY_CSS
 #define BUTTON_PM  "<span class='pmButton' onclick=\"setCheckBoxesThatContain('%s',%s,true,'%s','','%s')\">%c</span>"
 #define BUTTON_DEF "<span class='pmButton' onclick=\"setCheckBoxesThatContain('%s',true,false,'%s','','%s'); " \
                                                     "setCheckBoxesThatContain('%s',false,false,'%s','_defOff','%s');\" style='width:56px;font-weight:normal; font-family:default;'>default</span>"
 #define DEFAULT_BUTTON(nameOrId,anc,beg,contains) printf(BUTTON_DEF,(nameOrId),        (beg),(contains),(nameOrId),(beg),(contains))
 #define    PLUS_BUTTON(nameOrId,anc,beg,contains) printf(BUTTON_PM, (nameOrId),"true", (beg),(contains),'+')
 #define   MINUS_BUTTON(nameOrId,anc,beg,contains) printf(BUTTON_PM, (nameOrId),"false",(beg),(contains),'-')
 #else///ifndef BUTTONS_BY_CSS
 #define PM_BUTTON  "<IMG height=18 width=18 onclick=\"setCheckBoxesThatContain('%s',%s,true,'%s','','%s');\" id=\"btn_%s\" src=\"../images/%s\" alt=\"%s\">\n"
 #define DEF_BUTTON "<IMG onclick=\"setCheckBoxesThatContain('%s',true,false,'%s','','%s'); setCheckBoxesThatContain('%s',false,false,'%s','_defOff','%s');\" id=\"btn_%s\" src=\"../images/%s\" alt=\"%s\">\n"
 #define DEFAULT_BUTTON(nameOrId,anc,beg,contains) printf(DEF_BUTTON,(nameOrId),        (beg),(contains),(nameOrId),(beg),(contains),(anc),"defaults_sm.png","default")
 #define    PLUS_BUTTON(nameOrId,anc,beg,contains) printf(PM_BUTTON, (nameOrId),"true", (beg),(contains),(anc),"add_sm.gif",   "+")
 #define   MINUS_BUTTON(nameOrId,anc,beg,contains) printf(PM_BUTTON, (nameOrId),"false",(beg),(contains),(anc),"remove_sm.gif","-")
 #endif///ndef BUTTONS_BY_CSS
 
-struct trackDb *wgEncodeDownloadDirKeeper(char *db, struct trackDb *tdb, struct hash *trackHash)
-/* Look up through self and parents, looking for someone responsible for handling
- * where the downloads are. */
-{
-if (!tdbIsDownloadsOnly(tdb) && !sameString(tdb->table, tdb->track) && trackHash)
-    {
-    tdb = hashFindVal(trackHash, tdb->table);
-    if (tdb == NULL)
-        errAbort("Can't find track for table %s in wgEncodeDownloadDirKeeper", tdb->table);
-    }
-return trackDbTopLevelSelfOrParent(tdb);
-}
-
-static char *htmlStringForDownloadsLink(char *database, struct trackDb *tdb,char *name,boolean nameIsFile,
-        struct hash *trackHash)
+static char *htmlStringForDownloadsLink(char *database, struct trackDb *tdb,char *name,boolean nameIsFile)
 // Returns an HTML string for a downloads link
 {
 // If has fileSortOrder, then link to new hgFileUi
 if (!nameIsFile && trackDbSetting(tdb, FILE_SORT_ORDER) != NULL)
     {
     char * link = needMem(PATH_LEN); // 512 should be enough
     safef(link,PATH_LEN,"<A HREF='%s?db=%s&g=%s' title='Downloadable Files...'>%s</A>", //  NOTE: TARGET=ucscDownloads   ??
         hgFileUiName(), database, /*cartSessionVarName(), cartSessionId(cart),*/ tdb->track, name); // Note the hgsid would be needed if downloads page ever saved fileSortOrder to cart.
     return link;
     }
 else if(trackDbSetting(tdb, "wgEncode") != NULL)  // Downloads directory if this is ENCODE
     {
-    struct trackDb *dirKeeper = wgEncodeDownloadDirKeeper(database, tdb, trackHash);
-    char *compositeDir = (sameWord(dirKeeper->type,"downloadsOnly")?dirKeeper->track:dirKeeper->table);
+    const char *compositeDir = metadataFindValue(tdb, MDB_OBJ_TYPE_COMPOSITE);
+    if (compositeDir != NULL)
+        {
     struct dyString *dyLink = dyStringCreate("<A HREF=\"http://%s/goldenPath/%s/%s/%s/%s\" title='Download %s' class='file' TARGET=ucscDownloads>%s</A>",
-            hDownloadsServer(),
-            trackDbSettingOrDefault(dirKeeper, "origAssembly",database),  // This may not be wise!!!
+                hDownloadsServer(), database,
             ENCODE_DCC_DOWNLOADS, compositeDir, (nameIsFile?name:""), nameIsFile?"file":"files",name);
     return dyStringCannibalize(&dyLink);
     }
+    }
 return NULL;
 }
 
-static boolean makeNamedDownloadsLink(char *database, struct trackDb *tdb,char *name,
-	struct hash *trackHash)
+static boolean makeNamedDownloadsLink(char *database, struct trackDb *tdb,char *name)
 // Make a downloads link (if appropriate and then returns TRUE)
 {
-char *htmlString = htmlStringForDownloadsLink(database,trackDbTopLevelSelfOrParent(tdb),name,FALSE,trackHash);
+char *htmlString = htmlStringForDownloadsLink(database,trackDbTopLevelSelfOrParent(tdb),name,FALSE);
 if (htmlString == NULL)
     return FALSE;
 
 printf("%s", htmlString);
 freeMem(htmlString);
 return TRUE;
 }
 
-boolean makeDownloadsLink(char *database, struct trackDb *tdb, struct hash *trackHash)
+boolean makeDownloadsLink(char *database, struct trackDb *tdb)
 // Make a downloads link (if appropriate and then returns TRUE)
 {
-return makeNamedDownloadsLink(database, tdb,"Downloads", trackHash);
+return makeNamedDownloadsLink(database, tdb,"Downloads");
 }
 
 void makeTopLink(struct trackDb *tdb)
 /* Link to top of UI page */
 {
 if (trackDbSetting(tdb, "dimensions"))
     {
     char *upArrow = "&uArr;";
     enum browserType browser = cgiBrowser();
     if (browser == btIE || browser == btFF)
         upArrow = "&uarr;";
     // Note: the nested spans are so that javascript can determine position and selectively display the link when appropriate
     printf("<span class='navUp' style='float:right; display:none'>&nbsp;&nbsp;<A HREF='#' TITLE='Return to top of page'>Top%s</A></span>",upArrow);
     }
 }
@@ -161,31 +147,31 @@
     {
     char *encFile = cgiEncode(file);
     dyLink = dyStringCreate(VOCAB_LINK_WITH_FILE,encFile,encTerm,encValue,title,label);
     freeMem(encFile);
     }
 else
     dyLink = dyStringCreate(VOCAB_LINK,encTerm,encValue,title,label);
 if (suffix != NULL)
     dyStringAppend(dyLink,suffix);  // Don't encode since this may contain HTML
 
 freeMem(encTerm);
 freeMem(encValue);
 return dyStringCannibalize(&dyLink);
 }
 
-char *metadataAsHtmlTable(char *db,struct trackDb *tdb,boolean showLongLabel,boolean showShortLabel, struct hash *trackHash)
+char *metadataAsHtmlTable(char *db,struct trackDb *tdb,boolean showLongLabel,boolean showShortLabel)
 /* If metadata from metaDb exists, return string of html with table definition */
 {
 const struct mdbObj *safeObj = metadataForTable(db,tdb,NULL);
 if (safeObj == NULL || safeObj->vars == NULL)
 return NULL;
 
 //struct dyString *dyTable = dyStringCreate("<table id='mdb_%s'>",tdb->table);
 struct dyString *dyTable = dyStringCreate("<table style='display:inline-table;'>");
 if(showLongLabel)
     dyStringPrintf(dyTable,"<tr valign='bottom'><td colspan=2 nowrap>%s</td></tr>",tdb->longLabel);
 if(showShortLabel)
     dyStringPrintf(dyTable,"<tr valign='bottom'><td align='right' nowrap><i>shortLabel:</i></td><td nowrap>%s</td></tr>",tdb->shortLabel);
 
 // Get the hash of mdb and cv term types
 struct hash *cvTermTypes = (struct hash *)cvTermTypeHash();
@@ -194,31 +180,31 @@
 mdbObjRemoveVars(mdbObj,MDB_OBJ_TYPE_COMPOSITE " " MDB_VAR_PROJECT " " MDB_OBJ_TYPE " " MDB_VAR_MD5SUM); // Don't bother showing these (NOTE: composite,objType should be added to cv.ra typeOfTerms as hidden)
 mdbObjRemoveHiddenVars(mdbObj);
 mdbObjReorderByCv(mdbObj,FALSE);// Use cv defined order for visible vars
 struct mdbVar *mdbVar;
 for (mdbVar=mdbObj->vars;mdbVar!=NULL;mdbVar=mdbVar->next)
     {
     if ((sameString(mdbVar->var,MDB_VAR_FILENAME) || sameString(mdbVar->var,MDB_VAR_FILEINDEX) )
     && trackDbSettingClosestToHome(tdb,MDB_VAL_ENCODE_PROJECT) != NULL)
         {
         dyStringPrintf(dyTable,"<tr valign='top'><td align='right' nowrap><i>%s:</i></td><td nowrap>",mdbVar->var);
 
         struct slName *fileSet = slNameListFromComma(mdbVar->val);
         while (fileSet != NULL)
             {
             struct slName *file = slPopHead(&fileSet);
-            dyStringAppend(dyTable,htmlStringForDownloadsLink(db, tdb, file->name, TRUE, trackHash));
+            dyStringAppend(dyTable,htmlStringForDownloadsLink(db, tdb, file->name, TRUE));
             if (fileSet != NULL)
                 dyStringAppend(dyTable,"<BR>");
             slNameFree(&file);
             }
         dyStringAppend(dyTable,"</td></tr>");
         }
     else
         {
         if (cvTermTypes && differentString(mdbVar->var,MDB_VAR_TABLENAME)) // Don't bother with tableName
             {
             struct hash *cvTerm = hashFindVal(cvTermTypes,mdbVar->var);
             if (cvTerm != NULL) // even if cvTerm isn't used, it proves that it exists and a link is desirable
                 {
                 if(!cvTermIsHidden(mdbVar->var))
                     {
@@ -235,50 +221,44 @@
                         dyStringPrintf(dyTable,"<tr valign='bottom'><td align='right' nowrap><i>%s:</i></td><td nowrap>%s</td></tr>",linkOfType,mdbVar->val);
                     freeMem(linkOfType);
                     continue;
                     }
                 }
             }
         dyStringPrintf(dyTable,"<tr valign='bottom'><td align='right' nowrap><i>%s:</i></td><td nowrap>%s</td></tr>",mdbVar->var,mdbVar->val);
         }
     }
 dyStringAppend(dyTable,"</table>");
 //mdbObjsFree(&mdbObj); // spill some memory
 return dyStringCannibalize(&dyTable);
 }
 
 boolean compositeMetadataToggle(char *db,struct trackDb *tdb,char *title,
-        boolean embeddedInText,boolean showLongLabel, struct hash *trackHash)
+        boolean embeddedInText,boolean showLongLabel)
 /* If metadata from metaTbl exists, create a link that will allow toggling it's display */
 {
 const struct mdbObj *safeObj = metadataForTable(db,tdb,NULL);
 if(safeObj == NULL || safeObj->vars == NULL)
 return FALSE;
 
 printf("%s<A HREF='#a_meta_%s' onclick='return metadataShowHide(\"%s\",%s,true);' title='Show metadata details...'>%s<img src='../images/downBlue.png'/></A>",
         (embeddedInText?"&nbsp;":"<P>"),tdb->track,tdb->track, showLongLabel?"true":"false", (title?title:""));
-if (!sameString(tdb->table, tdb->track) && trackHash != NULL) // If trackHash is needed, then can't fill this in with ajax
-    {
-    printf("<DIV id='div_%s_meta' style='display:none;'>%s</div>",tdb->track,
-        metadataAsHtmlTable(db,tdb,showLongLabel,TRUE,trackHash) );
-    }
-else
     printf("<DIV id='div_%s_meta' style='display:none;'></div>",tdb->track);
 return TRUE;
 }
 
-void extraUiLinks(char *db,struct trackDb *tdb, struct hash *trackHash)
+void extraUiLinks(char *db,struct trackDb *tdb)
 /* Show downlaods, schema and metadata links where appropriate */
 {
 boolean schemaLink = (!tdbIsDownloadsOnly(tdb)
                   && isCustomTrack(tdb->table) == FALSE)
                   && (hTableOrSplitExists(db, tdb->table));
 boolean metadataLink = (!tdbIsComposite(tdb)
                   && metadataForTable(db, tdb, NULL) != NULL);
 boolean downloadLink = (trackDbSetting(tdb, "wgEncode") != NULL && !tdbIsSuperTrack(tdb));
 int links = 0;
 if (schemaLink)
     links++;
 if (metadataLink)
     links++;
 if (downloadLink)
     links++;
@@ -295,37 +275,37 @@
         printf(", ");
     }
 if(downloadLink)
     {
     // special case exception (hg18:NHGRI BiPs are in 7 different dbs but only hg18 has downloads):
     char *targetDb = trackDbSetting(tdb, "compareGenomeLinks");
     if (targetDb != NULL)
         {
         targetDb = cloneFirstWordByDelimiter(targetDb,'=');
         if (!startsWith("hg",targetDb))
             freez(&targetDb);
         }
     if (targetDb == NULL)
         targetDb = cloneString(db);
 
-    makeNamedDownloadsLink(targetDb, tdb, (links > 1 ? "downloads":"Downloads"), trackHash);
+    makeNamedDownloadsLink(targetDb, tdb, (links > 1 ? "downloads":"Downloads"));
     freez(&targetDb);
     if(metadataLink)
         printf(",");
     }
 if (metadataLink)
-    compositeMetadataToggle(db,tdb,"metadata", TRUE, TRUE, trackHash);
+    compositeMetadataToggle(db,tdb,"metadata", TRUE, TRUE);
 
 if(links > 1)
     printf("</td></tr></table>");
 }
 
 
 char *hUserCookie()
 /* Return our cookie name. */
 {
 return cfgOptionDefault("central.cookie", "hguid");
 }
 
 char *hDownloadsServer()
 /* get the downloads server from hg.conf or the default */
 {
@@ -3826,31 +3806,31 @@
     if (excludePast && !isEmpty(date) && dateIsOld(date,"%F"))
         freez(&date);
     }
 return date;
 }
 
 #ifndef SUBTRACK_CFG
 static void cfgLinkToDependentCfgs(struct cart *cart, struct trackDb *tdb,char *prefix)
 /* Link composite or view level controls to all associateled lower level controls */
 {
 if (!cartVarExists(cart, "ajax") && tdbIsComposite(tdb))
     printf("<script type='text/javascript'>compositeCfgRegisterOnchangeAction(\"%s\")</script>\n",prefix);
 }
 #endif///ndef SUBTRACK_CFG
 
-static void compositeUiSubtracks(char *db, struct cart *cart, struct trackDb *parentTdb,struct hash *trackHash)
+static void compositeUiSubtracks(char *db, struct cart *cart, struct trackDb *parentTdb)
 /* Display list of subtracks and descriptions with checkboxes to control visibility and possibly other
  * nice things including links to schema and metadata and a release date. */
 {
 struct trackDb *subtrack;
 struct dyString *dyHtml = newDyString(SMALLBUF);
 //char *colors[2]   = { COLOR_BG_DEFAULT,
 //                      COLOR_BG_ALTDEFAULT };
 char *colors[2]   = { "bgLevel1",
                       "bgLevel1" };
 int colorIx = COLOR_BG_DEFAULT_IX; // Start with non-default allows alternation
 #ifndef SUBTRACK_CFG
 boolean dependentCfgsNeedBinding = FALSE;
 #endif///ndef SUBTRACK_CFG
 
 // Get list of leaf subtracks to work with
@@ -4127,41 +4107,41 @@
         safef(buffer, sizeof(buffer), "%s.priority", subtrack->track);
         float priority = (float)cartUsualDouble(cart, buffer, subtrack->priority);
         printf("<INPUT TYPE=HIDDEN NAME='%s' class='trPos' VALUE=\"%.0f\">", buffer, priority); // keeing track of priority
         }
 
     // The checkbox has identifying classes including subCB and the tag for each dimension (e.g. class='subCB GM12878 CTCF Peak')
     dyStringClear(dyHtml);
     dyStringAppend(dyHtml, "subCB"); // always first
     if (membersForAll->dimensions)
         {
         for(di=dimX;di<membersForAll->dimMax;di++)
             {
             if (membersForAll->members[di] && -1 != (ix = stringArrayIx(membersForAll->members[di]->groupTag, membership->subgroups, membership->count)))
                 dyStringPrintf(dyHtml," %s",membership->membership[ix]);
             }
-        if (membersForAll->members[dimV] && -1 != (ix = stringArrayIx(membersForAll->members[dimV]->groupTag, membership->subgroups, membership->count)))
-            dyStringPrintf(dyHtml, " %s",membership->membership[ix]);  // Saved view for last
         }
      else if (membersForAll->abcCount) // "dimensions" don't exist but there may be subgroups anyway
         {
         for(di=dimA;di<membersForAll->dimMax;di++)
             {
             if (membersForAll->members[di] && -1 != (ix = stringArrayIx(membersForAll->members[di]->groupTag, membership->subgroups, membership->count)))
                 dyStringPrintf(dyHtml," %s",membership->membership[ix]);
             }
         }
+    if (membersForAll->members[dimV] && -1 != (ix = stringArrayIx(membersForAll->members[dimV]->groupTag, membership->subgroups, membership->count)))
+        dyStringPrintf(dyHtml, " %s",membership->membership[ix]);  // Saved view for last
 
     // And finally the checkBox is made!
     safef(buffer, sizeof(buffer), "%s_sel", subtrack->track);
 #ifdef SUBTRACK_CFG
     if (!enabledCB)
         {
         dyStringAppend(dyHtml, " disabled");
         cgiMakeCheckBoxFourWay(buffer,checkedCB,enabledCB,id,dyStringContents(dyHtml),"onclick='matSubCbClick(this);' style='cursor:pointer' title='view is hidden'");
         }
     else
 #endif///def SUBTRACK_CFG
         cgiMakeCheckBoxFourWay(buffer,checkedCB,enabledCB,id,dyStringContents(dyHtml),"onclick='matSubCbClick(this);' style='cursor:pointer'");
     if (useDragAndDrop)
         printf("&nbsp;");
 
@@ -4231,31 +4211,31 @@
         printf ("<TD>&nbsp;");
         indentIfNeeded(hierarchy,membership);
     #ifndef SUBTRACK_CFG
         if (cType != cfgNone)
             MAKE_CFG_SUBTRACK_LINK(subtrack->track,subtrack->shortLabel);
         else
     #endif///ndef SUBTRACK_CFG
             printf("%s",subtrack->shortLabel);
         puts ("</TD>");
         }
 
     // The long label column (note that it may have a "..." that allows getting at all the metadata)
     printf ("<TD title='select to copy'>&nbsp;%s", subtrack->longLabel);
     if (trackDbSetting(parentTdb, "wgEncode") && trackDbSetting(subtrack, "accession"))
         printf (" [GEO:%s]", trackDbSetting(subtrack, "accession"));
-    compositeMetadataToggle(db,subtrack,NULL,TRUE,FALSE, trackHash);
+    compositeMetadataToggle(db,subtrack,NULL,TRUE,FALSE);
     printf("&nbsp;");
 
     // Embedded cfg dialogs are within the TD that contains the longLabel.  This allows a wide item to be embedded in the table
     if (cType != cfgNone)
         {
     #ifdef SUBTRACK_CFG
         // How to make this thing float to the left?  Container is overflow:visible
         // and contained (made in js) is position:relative; left: -{some pixels}
         #define CFG_SUBTRACK_DIV "<DIV id='div_cfg_%s' class='subCfg %s' style='display:none; overflow:visible;'></DIV>"
         #define MAKE_CFG_SUBTRACK_DIV(table,view) printf(CFG_SUBTRACK_DIV,(table),(view)?(view):"noView")
         char * view = NULL;
         if (membersForAll->members[dimV] && -1 != (ix = stringArrayIx(membersForAll->members[dimV]->groupTag, membership->subgroups, membership->count)))
             view = membership->membership[ix];
         MAKE_CFG_SUBTRACK_DIV(subtrack->track,view);
     #else///ifndef SUBTRACK_CFG
@@ -7187,58 +7167,58 @@
                         if (hSameTrackDbType(primaryType, subtrack->type))
                             cartSetBoolean(cart, option, newVal);
                         }
                     else
                         cartSetBoolean(cart, option, newVal);
                     }
                 }
             }
         }
     puts ("</TABLE>");
     }
     return TRUE;
 }
 
 void hCompositeUi(char *db, struct cart *cart, struct trackDb *tdb,
-		  char *primarySubtrack, char *fakeSubmit, char *formName, struct hash *trackHash)
+		  char *primarySubtrack, char *fakeSubmit, char *formName)
 /* UI for composite tracks: subtrack selection.  If primarySubtrack is
  * non-NULL, don't allow it to be cleared and only offer subtracks
  * that have the same type.  If fakeSubmit is non-NULL, add a hidden
  * var with that name so it looks like it was pressed. */
 {
 bool hasSubgroups = (trackDbSetting(tdb, "subGroup1") != NULL);
 boolean isMatrix = dimensionsExist(tdb);
 boolean viewsOnly = FALSE;
 
 if (primarySubtrack == NULL && !cartVarExists(cart, "ajax"))
     {
     if(trackDbSetting(tdb, "dragAndDrop") != NULL)
         jsIncludeFile("jquery.tablednd.js", NULL);
     jsIncludeFile("ajax.js",NULL);
     jsIncludeFile("hui.js",NULL);
 #ifdef SUBTRACK_CFG
     jsIncludeFile("subCfg.js",NULL);
 #endif///ndef SUBTRACK_CFG
     }
 
 cgiDown(0.7);
 if (trackDbCountDescendantLeaves(tdb) < MANY_SUBTRACKS && !hasSubgroups)
     {
     if(primarySubtrack)
         compositeUiSubtracksMatchingPrimary(db, cart, tdb,primarySubtrack);
     else
-        compositeUiSubtracks(db, cart, tdb, trackHash);
+        compositeUiSubtracks(db, cart, tdb);
     return;
     }
 if (fakeSubmit)
     cgiMakeHiddenVar(fakeSubmit, "submit");
 
 if(primarySubtrack == NULL)
     {
     if(subgroupingExists(tdb,"view"))
         {
         hCompositeDisplayViewDropDowns(db, cart,tdb);
         if(subgroupCount(tdb) <= 1)
             viewsOnly = TRUE;
         }
     if(!viewsOnly)
         {
@@ -7252,31 +7232,31 @@
             compositeUiNoMatrix(db, cart,tdb,primarySubtrack,formName);
 	    }
         else
 	    {
             compositeUiByMatrix(db, cart, tdb, formName);
 	    }
         }
     }
 
 cartSaveSession(cart);
 cgiContinueHiddenVar("g");
 
 if(primarySubtrack)
     compositeUiSubtracksMatchingPrimary(db, cart, tdb,primarySubtrack);
 else
-    compositeUiSubtracks(db, cart, tdb, trackHash);
+    compositeUiSubtracks(db, cart, tdb);
 
 if (primarySubtrack == NULL)  // primarySubtrack is set for tableBrowser but not hgTrackUi
     {
     if (trackDbCountDescendantLeaves(tdb) > 5)
         {
         cgiDown(0.7);
         cgiMakeButton("Submit", "Submit");
         }
     }
 }
 
 boolean superTrackDropDownWithExtra(struct cart *cart, struct trackDb *tdb,
                                 int visibleChild,char *extra)
 /* Displays hide/show dropdown for supertrack.
  * Set visibleChild to indicate whether 'show' should be grayed