d1dafcb2502a7c2fd549c0bf978f15920a817a37
kate
  Mon May 6 15:22:05 2019 -0700
Fix problem with +/- buttons at buttoms of big matrix.  They were being created with non-unique ID. refs #20532

diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index 71f92cd..4b18ece 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -7455,38 +7455,38 @@
 freeMem(words[0]);
 freeMem(rootLabel);
 return cloneString(label);
 }
 
 #define PM_BUTTON_UC "<IMG height=18 width=18 id='%s' src='../images/%s'>"
 #define PM_BUTTON_UC_JS "return (matSetMatrixCheckBoxes(%s%s%s%s%s%s) == false);" 
 #define PM_MAKE_BUTTON_UC(s1,s2,s3,s4,s5,s6,name,img) \
     safef(id, sizeof id, "btn_%s", (name)); \
     printf(PM_BUTTON_UC, id, (img)); \
     safef(javascript, sizeof javascript, PM_BUTTON_UC_JS, (s1),(s2),(s3),(s4),(s5),(s6)); \
     jsOnEventById("click", id, javascript);
 #define MATRIX_RIGHT_BUTTONS_AFTER 8
 #define MATRIX_BOTTOM_BUTTONS_AFTER 20
 
-static void buttonsForAll(boolean left)
+static void buttonsForAll(boolean left, boolean top)
 {
 char id[256];
 char javascript[1024];
 char fullname[256];
-safef(fullname, sizeof fullname, "plus_all_%s" , left?"left":"right");
+safef(fullname, sizeof fullname, "plus_all_%s_%s", left ? "left" : "right", top ? "top" : "bottom");
 PM_MAKE_BUTTON_UC("true", "", "", "", "", "",  fullname,    "add_sm.gif")
-safef(fullname, sizeof fullname, "minus_all_%s", left?"left":"right");
+safef(fullname, sizeof fullname, "minus_all_%s_%s", left ? "left" : "right", top ? "top" : "bottom");
 PM_MAKE_BUTTON_UC("false","", "", "", "", "", fullname, "remove_sm.gif")
 }
 
 static void buttonsForOne(char *class, boolean vertical, boolean left)
 {
 char id[256];
 char javascript[1024];
 char fullname[256];
 safef(fullname, sizeof fullname, "plus_%s_all_%s" , class, left?"left":"right");
 PM_MAKE_BUTTON_UC("true",  ",'", class, "'", "", "", fullname,    "add_sm.gif")
 if (vertical)
     puts("<BR>");
 safef(fullname, sizeof fullname, "minus_%s_all_%s", class, left?"left":"right");
 PM_MAKE_BUTTON_UC("false", ",'", class, "'", "", "", fullname, "remove_sm.gif")
 }
@@ -7520,31 +7520,31 @@
 return FALSE;
 }
 
 static void matrixXheadingsRow1(char *db,struct trackDb *parentTdb,boolean squeeze,
                                 membersForAll_t* membersForAll,boolean top)
 // prints the top row of a matrix: 'All' buttons; X titles; buttons 'All'
 {
 members_t *dimensionX = membersForAll->members[dimX];
 members_t *dimensionY = membersForAll->members[dimY];
 
 printf("<TR ALIGN=CENTER valign=%s>\n",top?"BOTTOM":"TOP");
 if (dimensionX && dimensionY)
     {
     printf("<TH ALIGN=LEFT valign=%s>",top?"TOP":"BOTTOM");
     //printf("<TH ALIGN=LEFT valign=%s>",(top == squeeze)?"BOTTOM":"TOP");//"TOP":"BOTTOM");
-    buttonsForAll(TRUE);
+    buttonsForAll(TRUE, top);
     puts("&nbsp;All</TH>");
     }
 
 // If there is an X dimension, then titles go across the top
 if (dimensionX)
     {
     int ixX,cntX=0;
     if (dimensionY)
         {
         if (squeeze)
             printf("<TH align=RIGHT><div class='%s'><B><EM>%s</EM></B></div></TH>",
                    (top?"up45":"dn45"), dimensionX->groupTitle);
         else
             printf("<TH align=RIGHT><B><EM>%s</EM></B></TH>", dimensionX->groupTitle);
         }
@@ -7577,44 +7577,44 @@
                 }
             cntX++;
             }
         }
     // If dimension is big enough, then add Y buttons to right as well
     if (cntX>MATRIX_RIGHT_BUTTONS_AFTER)
         {
         if (dimensionY)
             {
             if (squeeze)
                 printf("<TH align=LEFT><div class='%s'><B><EM>%s</EM></B></div></TH>",
                        (top?"up45":"dn45"), dimensionX->groupTitle);
             else
                 printf("<TH align=LEFT><B><EM>%s</EM></B></TH>", dimensionX->groupTitle);
             printf("<TH ALIGN=RIGHT valign=%s>All&nbsp;",top?"TOP":"BOTTOM");
-            buttonsForAll(FALSE);
+            buttonsForAll(FALSE, top);
             puts("</TH>");
             }
         else
             printf("<TH ALIGN=LEFT valign=%s><B><EM>%s</EM></B>&nbsp;&nbsp;</TH>",
                    top ? "TOP" : "BOTTOM", dimensionX->groupTitle);
         }
     }
 else if (dimensionY)
     {
     printf("<TH ALIGN=RIGHT WIDTH=100 nowrap>");
     printf("<B><EM>%s</EM></B>", dimensionY->groupTitle);
     printf("</TH><TH ALIGN=CENTER WIDTH=60>");
-    buttonsForAll(FALSE);
+    buttonsForAll(FALSE, top);
     puts("</TH>");
     }
 puts("</TR>\n");
 }
 
 static void matrixXheadingsRow2(struct trackDb *parentTdb, boolean squeeze,
                                 membersForAll_t* membersForAll)
 // prints the 2nd row of a matrix: Y title; X buttons; title Y
 {
 members_t *dimensionX = membersForAll->members[dimX];
 members_t *dimensionY = membersForAll->members[dimY];
 
 // If there are both X and Y dimensions, then there is a row of buttons in X
 if (dimensionX && dimensionY)
     {
@@ -7675,31 +7675,31 @@
     {
     printf("<TH class='matCell all %s' ALIGN=%s nowrap colspan=2>",
            dimensionY->tags[ixY],left?"RIGHT":"LEFT");
     if (left)
         printf("%s&nbsp;",compositeLabelWithVocabLink(db,parentTdb,childTdb,dimensionY->groupTag,
                                                       dimensionY->titles[ixY]));
     buttonsForOne( dimensionY->tags[ixY], FALSE, left);
     if (!left)
         printf("&nbsp;%s",compositeLabelWithVocabLink(db,parentTdb,childTdb,dimensionY->groupTag,
                                                       dimensionY->titles[ixY]));
     puts("</TH>");
     }
 else if (dimensionX)
     {
     printf("<TH ALIGN=%s>",left?"RIGHT":"LEFT");
-    buttonsForAll(TRUE);
+    buttonsForAll(TRUE, TRUE);  // WARNING: not tested (is this used ?)
     puts("</TH>");
     }
 else if (left && dimensionY && childTdb != NULL)
     printf("<TH class='matCell all %s' ALIGN=RIGHT nowrap>%s</TH>\n",dimensionY->tags[ixY],
            compositeLabelWithVocabLink(db,parentTdb,childTdb,dimensionY->groupTag,
                                        dimensionY->titles[ixY]));
 }
 
 static int displayABCdimensions(char *db,struct cart *cart, struct trackDb *parentTdb,
                                 struct slRef *subtrackRefList, membersForAll_t* membersForAll)
 // This will walk through all declared nonX&Y dimensions (X and Y is the 2D matrix of CBs.
 // NOTE: ABC dims are only supported if there are X & Y both.
 //       Also expected number should be passed in
 {
 int count=0,ix;