ca7d5327e325b074ce65c86f9ef7fea5be47ab25
tdreszer
  Wed Jul 20 11:13:05 2011 -0700
Initial check-in of not yet comple subtrack configuration module.
diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index e3ffd74..1a680c9 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -16,53 +16,54 @@
 #include "chainDb.h"
 #include "netCart.h"
 #include "obscure.h"
 #include "wiggle.h"
 #include "phyloTree.h"
 #include "hgMaf.h"
 #include "udc.h"
 #include "customTrack.h"
 #include "encode/encodePeak.h"
 #include "mdb.h"
 #include "web.h"
 #include "hPrint.h"
 #include "fileUi.h"
 #include "bigBed.h"
 #include "bigWig.h"
+#include "regexHelper.h"
 
 static char const rcsid[] = "$Id: hui.c,v 1.297 2010/06/02 19:27:51 tdreszer Exp $";
 
 #define SMALLBUF 128
 #define MAX_SUBGROUP 9
 #define ADD_BUTTON_LABEL        "add"
 #define CLEAR_BUTTON_LABEL      "clear"
 #define JBUFSIZE 2048
 
 //#define PM_BUTTON "<A NAME=\"%s\"></A><A HREF=\"#%s\"><IMG height=18 width=18 onclick=\"return (setCheckBoxesThatContain('%s',%s,true,'%s','','%s') == false);\" id=\"btn_%s\" src=\"../images/%s\" alt=\"%s\"></A>\n"
 //#define DEF_BUTTON "<A NAME=\"%s\"></A><A HREF=\"#%s\"><IMG onclick=\"setCheckBoxesThatContain('%s',true,false,'%s','','%s'); return (setCheckBoxesThatContain('%s',false,false,'%s','_defOff','%s') == false);\" id=\"btn_%s\" src=\"../images/%s\" alt=\"%s\"></A>\n"
 //#define DEFAULT_BUTTON(nameOrId,anc,beg,contains) printf(DEF_BUTTON,(anc),(anc),(nameOrId),        (beg),(contains),(nameOrId),(beg),(contains),(anc),"defaults_sm.png","default")
 //#define    PLUS_BUTTON(nameOrId,anc,beg,contains) printf(PM_BUTTON, (anc),(anc),(nameOrId),"true", (beg),(contains),(anc),"add_sm.gif",   "+")
 //#define   MINUS_BUTTON(nameOrId,anc,beg,contains) printf(PM_BUTTON, (anc),(anc),(nameOrId),"false",(beg),(contains),(anc),"remove_sm.gif","-")
 #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","-")
 
 #define ENCODE_DCC_DOWNLOADS "encodeDCC"
 
-//#define SUBTRACK_CFG_POPUP
+#define SUBTRACK_CFG
 
 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,
@@ -3489,49 +3490,53 @@
         if(notFirst)
             dyStringPrintf(dyClause, " AND ");
         dyStringAppend(dyClause, clause);
         freeMem(clause);
         notFirst = TRUE;
         }
     }
 if(dyStringLen(dyClause) == 0)
     {
     dyStringFree(&dyClause);
     return NULL;
     }
 return dyStringCannibalize(&dyClause);
 }
 
-void filterBySetCfgUi(struct trackDb *tdb, filterBy_t *filterBySet, boolean onOneLine)
+void filterBySetCfgUi(struct cart *cart, struct trackDb *tdb,
+                      filterBy_t *filterBySet, boolean onOneLine)
 /* Does the UI for a list of filterBy structure */
 {
 if(filterBySet == NULL)
     return;
 
 #define FILTERBY_HELP_LINK  "<A HREF=\"../goldenPath/help/multiView.html\" TARGET=ucscHelp>help</A>"
 int count = slCount(filterBySet);
 if(count == 1)
     puts("<TABLE cellpadding=3><TR valign='top'>");
 else
     printf("<B>Filter items by:</B> (select multiple categories and items - %s)<TABLE cellpadding=3><TR valign='top'>\n",FILTERBY_HELP_LINK);
 
 filterBy_t *filterBy = NULL;
+if(cartOptionalString(cart, "ajax") == NULL)
+    {
 webIncludeResourceFile("ui.dropdownchecklist.css");
 jsIncludeFile("ui.dropdownchecklist.js",NULL);
 #ifdef NEW_JQUERY
 jsIncludeFile("ddcl.js",NULL);
 #endif///def NEW_JQUERY
+    }
 
 int ix=0;
 for(filterBy = filterBySet;filterBy != NULL; filterBy = filterBy->next)
     {
     puts("<TD>");
     if(count == 1)
         printf("<B>Filter by %s</B> (select multiple items - %s)",filterBy->title,FILTERBY_HELP_LINK);
     else
         printf("<B>%s</B>",filterBy->title);
     printf("<BR>\n");
 
     // TODO: columnCount (Number of filterBoxes per row) should be configurable through tdb setting
     #ifdef NEW_JQUERY
         #define FILTER_BY_FORMAT "<SELECT id='fbc%d' name='%s.filterBy.%s' multiple style='display: none; font-size:.9em;' class='filterBy'><BR>\n"
     #else///ifndef NEW_JQUERY
@@ -3798,55 +3803,53 @@
     if(date)
         {
         addMonths = TRUE;
         date = cloneString(date); // all returns should be freeable memory
         }
     }
 if (date != NULL)
     {
     date = strSwapChar(date, ' ', 0);   // Truncate time
     if(addMonths)
         date = dateAddTo(date, "%F", 0, 9, 0);
     }
 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))
-#ifdef SUBTRACK_CFG_POPUP
-    printf("<script type='text/javascript'>registerViewOnchangeAction('%s')</script>\n",prefix);
-#else///ifndef SUBTRACK_CFG_POPUP
     printf("<script type='text/javascript'>compositeCfgRegisterOnchangeAction(\"%s\")</script>\n",prefix);
-#endif///ndef SUBTRACK_CFG_POPUP
 }
+#endif///ndef SUBTRACK_CFG
 
 static void compositeUiSubtracks(char *db, struct cart *cart, struct trackDb *parentTdb,struct hash *trackHash)
 /* 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_POPUP
+#ifndef SUBTRACK_CFG
 boolean dependentCfgsNeedBinding = FALSE;
-#endif///ndef SUBTRACK_CFG_POPUP
+#endif///ndef SUBTRACK_CFG
 
 // Get list of leaf subtracks to work with
 struct slRef *subtrackRef, *subtrackRefList = trackDbListGetRefsToDescendantLeaves(parentTdb->subtracks);
 
 // Look for dividers, heirarchy, dimensions, sort and dragAndDrop!
 char **lastDivide = NULL;
 dividers_t *dividers = dividersSettingGet(parentTdb);
 if (dividers)
     lastDivide = needMem(sizeof(char*)*dividers->count);
 hierarchy_t *hierarchy = hierarchySettingGet(parentTdb);
 
 membersForAll_t* membersForAll = membersForAllSubGroupsGet(parentTdb,NULL);
 int dimCount=0,di;
 for(di=0;di<membersForAll->dimMax;di++) { if (membersForAll->members[di]) dimCount++; }
 sortOrder_t* sortOrder = sortOrderGet(cart,parentTdb);
@@ -4012,37 +4015,43 @@
     preSorted = TRUE;
     puts("<TBODY>");
     }
 
 // Finally the big "for loop" to list each subtrack as a table row.
 for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next)
     {
     subtrack = subtrackRef->val;
     int ix;
 
     // Determine whether subtrack is checked, visible, configurable, has group membership, etc.
     int fourState = subtrackFourStateChecked(subtrack,cart);
     boolean checkedCB = fourStateChecked(fourState);
     boolean enabledCB = fourStateEnabled(fourState);
     eCfgType cType = cfgTypeFromTdb(subtrack,FALSE);
-#ifdef SUBTRACK_CFG_POPUP
-    // Turn this off only if configurable explicitly set to off
-    if (trackDbSettingClosestToHome(subtrack, "configurable") && trackDbSettingClosestToHomeOn(subtrack, "configurable") == FALSE)
-#else///ifndef SUBTRACK_CFG_POPUP
+    if (cType != cfgNone)
+        {
+    #ifdef SUBTRACK_CFG
+        // Turn off configuring for certain track type or if explicitly turned off
+        if (regexMatch(subtrack->track, "^snp[0-9]+")     // Special cases to be removed
+        ||  regexMatch(subtrack->track, "^cons[0-9]+way") // (matches logic in json setup in imageV2.c)
+        ||  regexMatch(subtrack->track, "^multiz")
+        ||  SETTING_IS_OFF(trackDbSettingClosestToHome(subtrack, "configureByPopup")))
+    #else///ifndef SUBTRACK_CFG
     if (trackDbSettingClosestToHomeOn(subtrack, "configurable") == FALSE)
-#endif///ndef SUBTRACK_CFG_POPUP
+    #endif///ndef SUBTRACK_CFG
         cType = cfgNone;
+        }
     membership_t *membership = subgroupMembershipGet(subtrack);
 
     if (sortOrder == NULL && !useDragAndDrop)
         {
         if ( divisionIfNeeded(lastDivide,dividers,membership) )
             colorIx = (colorIx == COLOR_BG_DEFAULT_IX ? COLOR_BG_ALTDEFAULT_IX : COLOR_BG_DEFAULT_IX);
         }
 
     // Start the TR which must have an id that is directly related to the checkBox id
     char *id = checkBoxIdMakeForTrack(subtrack,membersForAll->members,membersForAll->dimMax,membership); // view is known tag
     printf("<TR valign='top' class='%s%s'",colors[colorIx],(useDragAndDrop?" trDraggable":""));
     printf(" id=tr_%s p%s>\n",id,(!displayAll?" style='display:none'":""));
 
     // Now the TD that holds the checkbox
     printf("<TD%s%s>",
@@ -4055,132 +4064,130 @@
     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
 
     // And finally the checkBox is made!
     char htmlIdentifier[SMALLBUF];
     safef(htmlIdentifier, sizeof(htmlIdentifier), "%s_sel", subtrack->track);
     cgiMakeCheckBoxFourWay(htmlIdentifier,checkedCB,enabledCB,id,dyStringContents(dyHtml),"onclick='matSubCbClick(this);' style='cursor:pointer'");
     if (useDragAndDrop)
         printf("&nbsp;");
 
-    // TODO: make a "view" dropdown (fake to save rendering time) and a configurable wrench here right after the checkbox
+#ifdef SUBTRACK_CFG
+    if (cType != cfgNone)  // make a wrench
+        {
+        // TODO: make vis dd or vis text inp or vis img.  Alternatively, make '*' to denote there are subtrack level differences.
+        enum trackVisibility vis = tdbVisLimitedByAncestry(cart, subtrack, TRUE);
+        #define SUBTRACK_CFG_WRENCH "<a href='#a_cfg' onclick='return scm.cfgToggle(\"%s\");' title='Configure this %s subtrack'><img src='../images/wrench.png'></a>\n"
+        printf(SUBTRACK_CFG_WRENCH,subtrack->track,hStringFromTv(vis));
+        //#define SUBTRACK_CFG_WRENCH "<a href='#a_cfg' onclick='return scm.cfgToggle(\"%s\");' title='Configure this subtrack'><img src='../images/wrench.png'></a>\n"
+        //printf(SUBTRACK_CFG_WRENCH,subtrack->track);
+        }
+#endif///def SUBTRACK_CFG
 
     // A hidden field to keep track of subtrack order if it could change
     if (sortOrder != NULL || useDragAndDrop)
         {
         safef(htmlIdentifier, sizeof(htmlIdentifier), "%s.priority", subtrack->track);
         float priority = (float)cartUsualDouble(cart, htmlIdentifier, subtrack->priority);
         printf("<INPUT TYPE=HIDDEN NAME='%s' class='trPos' VALUE=\"%.0f\">", htmlIdentifier, priority); // keeing track of priority
         }
 
     // A color patch which helps distinguish subtracks in some types of composites
     if (doColorPatch)
         {
         printf("<TD BGCOLOR='#%02X%02X%02X'>&nbsp;&nbsp;&nbsp;&nbsp;</TD>",
                 subtrack->colorR, subtrack->colorG, subtrack->colorB);
         }
 
-    // Subtrack configuration requires a field that is a link to an embedded (or popup) dialog
-#ifdef SUBTRACK_CFG_POPUP
-    #define CFG_SUBTRACK_LINK  "<A HREF='#a_cfg_%s' onclick='return popUpSubtrackCfg(\"%s\",\"%s\");' title='%s'>%s</A>"
-    #define MAKE_CFG_SUBTRACK_LINK(table,label,title) printf(CFG_SUBTRACK_LINK, (table),(table),(label),(label),(title))
-    struct dyString *dyLabel = newDyString(128);
-#else///ifndef SUBTRACK_CFG_POPUP
-    #define CFG_SUBTRACK_LINK  "<A HREF='#a_cfg_%s' onclick='return subtrackCfgShow(\"%s\");' title='Subtrack Configuration'>%s</A>"
-    #define MAKE_CFG_SUBTRACK_LINK(table,title) printf(CFG_SUBTRACK_LINK, (table),(table),(title))
-#endif///ndef SUBTRACK_CFG_POPUP
-
     // If sortable, then there must be a column per sortable dimension
     if (sortOrder != NULL)
         {
         int sIx=0;
         for(sIx=0;sIx<sortOrder->count;sIx++)
             {
             ix = stringArrayIx(sortOrder->column[sIx], membership->subgroups, membership->count); // TODO: Sort needs to expand from subGroups to labels as well
             if (ix >= 0)
                 {
                 char *titleRoot=NULL;
                 if (cvTermIsEmpty(sortOrder->column[sIx],membership->titles[ix]))
                     titleRoot = cloneString(" &nbsp;");
                 else
                     titleRoot = labelRoot(membership->titles[ix],NULL);
                 // Each sortable column requires hidden goop (in the "abbr" field currently) which is the actual sort on value
                 printf ("<TD id='%s_%s' abbr='%s' align='left'>&nbsp;",subtrack->track,sortOrder->column[sIx],membership->membership[ix]);
-            #ifdef SUBTRACK_CFG_POPUP
-                dyStringPrintf(dyLabel,"%s ",titleRoot);
-                if (cType != cfgNone && sameString("view",sortOrder->column[sIx])) // configure link is on view currenntly  TODO: make a wrench next to check box/view
-                    {
-                    dyStringAppend(dyLabel,"Configuration");
-                    MAKE_CFG_SUBTRACK_LINK(subtrack->track,dyStringContents(dyLabel),titleRoot);
-                    }
-            #else///ifndef SUBTRACK_CFG_POPUP
-                if (cType != cfgNone && sameString("view",sortOrder->column[sIx]))
-                    MAKE_CFG_SUBTRACK_LINK(subtrack->track,titleRoot);  // FIXME: Currently configurable under sort only supported when multiview
-            #endif///ndef SUBTRACK_CFG_POPUP
+            #ifndef SUBTRACK_CFG
+                #define CFG_SUBTRACK_LINK  "<A HREF='#a_cfg_%s' onclick='return subtrackCfgShow(\"%s\");' title='Subtrack Configuration'>%s</A>"
+                #define MAKE_CFG_SUBTRACK_LINK(table,title) printf(CFG_SUBTRACK_LINK, (table),(table),(title))
+                if (cType != cfgNone && sameString("view",sortOrder->column[sIx])) // configure link is on view currently
+                    MAKE_CFG_SUBTRACK_LINK(subtrack->track,titleRoot);
                 else
+            #endif///ndef SUBTRACK_CFG
                     printf("%s",titleRoot);
                 puts ("</TD>");
                 freeMem(titleRoot);
                 }
             }
         }
     else  // Non-sortable tables do not have sort by columns but will display a short label (which may be a configurable link)
         {
         printf ("<TD>&nbsp;");
         indentIfNeeded(hierarchy,membership);
-    #ifdef SUBTRACK_CFG_POPUP
-        if (cType != cfgNone && cType != cfgWigMaf)  // FIXME: wigMaf restriction is temporary until configureByPopup off is set
-            MAKE_CFG_SUBTRACK_LINK(subtrack->track,subtrack->shortLabel,subtrack->shortLabel);
-    #else///ifndef SUBTRACK_CFG_POPUP
+    #ifndef SUBTRACK_CFG
         if (cType != cfgNone)
             MAKE_CFG_SUBTRACK_LINK(subtrack->track,subtrack->shortLabel);
-    #endif///ndef SUBTRACK_CFG_POPUP
         else
+    #endif///ndef SUBTRACK_CFG
             printf("%s",subtrack->shortLabel);
         puts ("</TD>");
         }
-#ifdef SUBTRACK_CFG_POPUP
-    dyStringFree(&dyLabel);
-#endif///def SUBTRACK_CFG_POPUP
 
     // 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);
     printf("&nbsp;");
 
-#ifndef SUBTRACK_CFG_POPUP
     // 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
         dependentCfgsNeedBinding = TRUE; // configurable subtrack needs to be bound to composite settings
     #define CFG_SUBTRACK_DIV "<DIV id='div_%s_cfg'%s><INPUT TYPE=HIDDEN NAME='%s' value='%s'>\n"
     #define MAKE_CFG_SUBTRACK_DIV(table,cfgVar,open) printf(CFG_SUBTRACK_DIV,(table),((open)?"":" style='display:none'"),(cfgVar),((open)?"on":"off"))
         safef(htmlIdentifier,sizeof(htmlIdentifier),"%s.childShowCfg",subtrack->track);
         boolean open = cartUsualBoolean(cart, htmlIdentifier,FALSE);
         MAKE_CFG_SUBTRACK_DIV(subtrack->track,htmlIdentifier,open);
         safef(htmlIdentifier,sizeof(htmlIdentifier),"%s",subtrack->track);
         cfgByCfgType(cType,db,cart,subtrack,htmlIdentifier,"Subtrack",TRUE);
         printf("</DIV>");
+    #endif///ndef SUBTRACK_CFG
         }
-#endif///ndef SUBTRACK_CFG_POPUP
 
     // A schema link for each track
     printf("</td>\n<TD>&nbsp;");
     makeSchemaLink(db,subtrack,"schema");
     printf("&nbsp;");
 
     // Do we have a restricted until date?
     if (restrictions)
         {
         char *dateDisplay = encodeRestrictionDateDisplay(db,subtrack);
         if (dateDisplay)
             {
             if (dateIsOld(dateDisplay,"%F"))
                 printf("</TD>\n<TD align='center' nowrap style='color: #BBBBBB;'>&nbsp;%s&nbsp;", dateDisplay);
             else
@@ -4205,34 +4212,34 @@
     if (slCount(subtrackRefList) > 5)
         printf("<span class='subCBcount'></span>\n");
 
     // Restruction policy needs a link
     if (restrictions && sortOrder != NULL)
         printf("</TD><TH><A HREF='%s' TARGET=BLANK style='font-size:.9em;'>Restriction Policy</A>", ENCODE_DATA_RELEASE_POLICY);
 
     printf("</TD></TR></TFOOT>\n");
     }
 puts("</TABLE>");
 if (sortOrder == NULL)
     printf("</td></tr></table>");
 
 // Tying subtracks with matrix and subtrack cfgs with views requires javascript help
 puts("<script type='text/javascript'>matInitializeMatrix();</script>");
-#ifndef SUBTRACK_CFG_POPUP
+#ifndef SUBTRACK_CFG
 if (dependentCfgsNeedBinding)
     cfgLinkToDependentCfgs(cart,parentTdb,parentTdb->track);
-#endif//ndef SUBTRACK_CFG_POPUP
+#endif//ndef SUBTRACK_CFG
 
 // Finally we are free of all this
 membersForAllSubGroupsFree(parentTdb,&membersForAll);
 dyStringFree(&dyHtml)
 sortOrderFree(&sortOrder);
 dividersFree(&dividers);
 hierarchyFree(&hierarchy);
 }
 
 static void compositeUiSubtracksMatchingPrimary(char *db, struct cart *cart, struct trackDb *parentTdb,char *primarySubtrack)
 /* Display list of subtracks associated with a primary subtrack for the hgTables merge function */
 {
 assert(primarySubtrack != NULL);
 char *primaryType = getPrimaryType(primarySubtrack, parentTdb);
 char htmlIdentifier[SMALLBUF];
@@ -4874,31 +4881,31 @@
 #ifdef ALL_SCORE_FILTERS_LOGIC
 // Numeric filters are first
 boolean isBoxOpened = FALSE;
 if (numericFiltersShowAll(cart, tdb, &isBoxOpened, boxed, compositeLevel, name, title) > 0)
     skipScoreFilter = TRUE;
 #endif///def ALL_SCORE_FILTERS_LOGIC
 
 // Add any multi-selects next
 if(filterBySet != NULL)
     {
     if(!tdbIsComposite(tdb) && cartOptionalString(cart, "ajax") == NULL)
         jsIncludeFile("hui.js",NULL);
 
     if (!isBoxOpened)   // Note filterBy boxes are not double "boxed", if there are no other filters
         printf("<BR>");
-    filterBySetCfgUi(tdb,filterBySet,TRUE);
+    filterBySetCfgUi(cart,tdb,filterBySet,TRUE);
     filterBySetFree(&filterBySet);
     skipScoreFilter = TRUE;
     }
 
 // For no good reason scoreFilter is incompatible with filterBy and or numericFilters
 // FIXME scoreFilter should be implemented inside numericFilters and is currently specificly excluded to avoid unexpected changes
 if (skipScoreFilter)
     {
     #ifdef ALL_SCORE_FILTERS_LOGIC
     if (isBoxOpened)
         cfgEndBox(boxed);
     #endif///def ALL_SCORE_FILTERS_LOGIC
 
     return; // Cannot have both '*filter' and 'scoreFilter'
     }
@@ -5356,31 +5363,31 @@
     printf("<p><b>Filter out NMD targets.</b>");
     cgiMakeCheckBox(varName, nmdDefault);
     }
 
 if(!sameString(tdb->track, "tigrGeneIndex")
 && !sameString(tdb->track, "ensGeneNonCoding")
 && !sameString(tdb->track, "encodeGencodeRaceFrags"))
     baseColorDropLists(cart, tdb, name);
 
 if (cartOptionalString(cart, "ajax") == NULL)
     {
     filterBy_t *filterBySet = filterBySetGet(tdb,cart,name);
     if(filterBySet != NULL)
         {
         printf("<BR>");
-        filterBySetCfgUi(tdb,filterBySet,FALSE);
+        filterBySetCfgUi(cart,tdb,filterBySet,FALSE);
         filterBySetFree(&filterBySet);
         }
     }
 cfgEndBox(boxed);
 }
 
 static boolean isSpeciesOn(struct cart *cart, struct trackDb *tdb, char *species, char *option, int optionSize, boolean defaultState)
 /* check the cart to see if species is turned off or on (default is defaultState) */
 {
 boolean ret = defaultState;
 safef(option, optionSize, "%s.%s", tdb->track, species);
 
 /* see if this is a simple multiz (not composite track) */
 char *s = cartOptionalString(cart, option);
 if (s != NULL)
@@ -6093,31 +6100,33 @@
             char *viewName = membersOfView->tags[ix];
             printf("<TR id=\"tr_cfg_%s\"", viewName);
             if((firstOpened == -1 && !compositeViewCfgExpandedByDefault(parentTdb,membersOfView->tags[ix],NULL))
                 || (firstOpened != -1 && firstOpened != ix))
                 printf(" style=\"display:none\"");
             printf("><TD width=10>&nbsp;</TD>");
             int ix2=ix;
             while(0 < ix2--)
                 printf("<TD width=100>&nbsp;</TD>");
             printf("<TD colspan=%d>",membersOfView->count+1);
             safef(varName, sizeof(varName), "%s", view->track);
             if(configurable[ix] != cfgNone)
                 {
                 cfgByCfgType(configurable[ix],db,cart,view->subtracks,varName,
                         membersOfView->titles[ix],TRUE);
+            #ifndef SUBTRACK_CFG
                 cfgLinkToDependentCfgs(cart,parentTdb,varName);
+            #endif///ndef SUBTRACK_CFG
                 }
             }
         }
     }
 puts("</TABLE>");
 subgroupMembersFree(&membersOfView);
 freeMem(matchedSubtracks);
 return TRUE;
 }
 
 char *compositeLabelWithVocabLink(char *db,struct trackDb *parentTdb, struct trackDb *childTdb,
 	char *vocabType, char *label)
 /* If the parentTdb has a controlledVocabulary setting and the vocabType is found,
    then label will be wrapped with the link to display it.  Return string is cloned. */
 {
@@ -6424,36 +6433,39 @@
             first = FALSE;
             }
         }
     }
 dyStringPrintf(dyLink,VOCAB_MULTILINK_END,members->groupTitle,members->groupTitle);
 freeMem(vocab);
 return dyStringCannibalize(&dyLink);
 }
 
 static boolean compositeUiByFilter(char *db, struct cart *cart, struct trackDb *parentTdb, char *formName)
 /* UI for composite tracks: filter subgroups by multiselects to select subtracks. */
 {
 membersForAll_t* membersForAll = membersForAllSubGroupsGet(parentTdb,cart);
 if(membersForAll == NULL || membersForAll->filters == FALSE) // Not Matrix or filters
     return FALSE;
+if(cartOptionalString(cart, "ajax") == NULL)
+    {
 jsIncludeFile("ui.core.js",NULL);
 webIncludeResourceFile("ui.dropdownchecklist.css");
 jsIncludeFile("ui.dropdownchecklist.js",NULL);
 #ifdef NEW_JQUERY
 jsIncludeFile("ddcl.js",NULL);
 #endif///def NEW_JQUERY
+    }
 
 cgiDown(0.7);
 printf("<B>Filter subtracks %sby:</B> (select multiple %sitems - %s)<BR>\n",
        (membersForAll->members[dimX] != NULL || membersForAll->members[dimY] != NULL ? "further ":""),
        (membersForAll->dimMax == dimA?"":"categories and "),FILTERBY_HELP_LINK);
 printf("<TABLE><TR valign='top'>\n");
 
 // Do All [+][-] buttons
 if(membersForAll->members[dimX] == NULL && membersForAll->members[dimY] == NULL) // No matrix
     {
     #define PM_BUTTON_FILTER_COMP "<input type='button' class='inOutButton' onclick=\"waitOnFunction(filterCompositeSet,this,%s); return false;\" id='btn_%s' value='%c'>"
     printf("<TD align='left' width='50px'><B>All:</B><BR>");
     printf(PM_BUTTON_FILTER_COMP,"true",  "plus_fc",'+');
     printf(PM_BUTTON_FILTER_COMP,"false","minus_fc",'-');
     //#define PM_BUTTON2_FILTER_COMP "<IMG height=18 width=18 onclick=\"filterCompositeSet(%s);\" id='btn_%s' src='../images/%s'>"
@@ -6885,48 +6897,44 @@
     }
     return TRUE;
 }
 
 void hCompositeUi(char *db, struct cart *cart, struct trackDb *tdb,
 		  char *primarySubtrack, char *fakeSubmit, char *formName, struct hash *trackHash)
 /* 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)
-    {
-    if (!cartVarExists(cart, "ajax"))
+if (primarySubtrack == NULL && !cartVarExists(cart, "ajax"))
         {
         if(trackDbSetting(tdb, "dragAndDrop") != NULL)
             jsIncludeFile("jquery.tablednd.js", NULL);
         jsIncludeFile("ajax.js",NULL);
         #ifdef TABLE_SCROLL
         jsIncludeFile("jquery.fixedtable.js",NULL);
         #endif//def TABLE_SCROLL
-        }
     jsIncludeFile("hui.js",NULL);
     }
 
-#ifdef SUBTRACK_CFG_POPUP
-printf("<div id='popit' style='display: none'></div>");
-cgiMakeHiddenVar("db", db);
-printf("<input type=HIDDEN id='track' value='%s';</input>\n",tdb->track);
+#ifdef SUBTRACK_CFG
+cgiMakeHiddenVar("db", db); // TODO: Change these to json vars as per Larry's new method
+printf("<input type=HIDDEN id='track' value='%s'>\n",tdb->track);
 #endif
 cgiDown(0.7);
 if (trackDbCountDescendantLeaves(tdb) < MANY_SUBTRACKS && !hasSubgroups)
     {
     if(primarySubtrack)
         compositeUiSubtracksMatchingPrimary(db, cart, tdb,primarySubtrack);
     else
         compositeUiSubtracks(db, cart, tdb, trackHash);
     return;
     }
 if (fakeSubmit)
     cgiMakeHiddenVar(fakeSubmit, "submit");
 
 if(primarySubtrack == NULL)
     {
@@ -6940,35 +6948,30 @@
         {
         cgiDown(0.7);
         if(trackDbSettingOn(tdb, "allButtonPair"))
 	    {
             compositeUiAllButtons(db, cart, tdb, formName);
 	    }
         else if (!hasSubgroups || !isMatrix || primarySubtrack)
 	    {
             compositeUiNoMatrix(db, cart,tdb,primarySubtrack,formName);
 	    }
         else
 	    {
             compositeUiByMatrix(db, cart, tdb, formName);
 	    }
         }
-#ifdef SUBTRACK_CFG_POPUP
-    if(primarySubtrack == NULL)
-        cfgLinkToDependentCfgs(cart,tdb,tdb->track);  // Must be after views are set up to get view vis
-    printf("<script type='text/javascript'>registerFormSubmit('mainForm');</script>\n");
-#endif
     }
 
 cartSaveSession(cart);
 cgiContinueHiddenVar("g");
 
 if(primarySubtrack)
     compositeUiSubtracksMatchingPrimary(db, cart, tdb,primarySubtrack);
 else
     compositeUiSubtracks(db, cart, tdb, trackHash);
 
 if (primarySubtrack == NULL)  // primarySubtrack is set for tableBrowser but not hgTrackUi
     {
     if (trackDbCountDescendantLeaves(tdb) > 5)
         {
         cgiDown(0.7);