26f820467afa323064eb88e948348545e9dc010b
max
  Fri Jul 29 14:31:08 2016 -0700
Adding a "Download All" button to the CIRM CDW. No redmine.

diff --git src/hg/lib/tablesTables.c src/hg/lib/tablesTables.c
index 2ec4a51..cdcfc0b 100644
--- src/hg/lib/tablesTables.c
+++ src/hg/lib/tablesTables.c
@@ -19,42 +19,44 @@
 /* Return fieldedTable from a database query */
 {
 struct sqlResult *sr = sqlGetResult(conn, query);
 char **fields;
 int fieldCount = sqlResultFieldArray(sr, &fields);
 struct fieldedTable *table = fieldedTableNew(query, fields, fieldCount);
 char **row;
 int i = 0;
 while ((row = sqlNextRow(sr)) != NULL)
     fieldedTableAdd(table, row, fieldCount, ++i);
 sqlFreeResult(&sr);
 return table;
 }
 
 static void showTableFilterInstructionsEtc(struct fieldedTable *table, 
-    char *itemPlural, struct  fieldedTableSegment *largerContext)
+    char *itemPlural, struct  fieldedTableSegment *largerContext, void (*addFunc)(void))
 /* Print instructional text, and basic summary info on who passes filter, and a submit
  * button just in case user needs it */
 {
 /* Print info on matching */
 int matchCount = slCount(table->rowList);
 if (largerContext != NULL)  // Need to page?
      matchCount = largerContext->tableSize;
 cgiMakeButton("submit", "search");
 printf("  &nbsp ");
 printf("%d %s found. ", matchCount, itemPlural);
 
+if (addFunc)
+    addFunc();
 
 printf("<BR>\n");
 printf("You can further filter search results field by field below. ");    
 printf("Wildcard * and ? characters are allowed in text fields. ");
 printf("&GT;min or &LT;max are allowed in numerical fields.<BR>\n");
 }
 
 static void printSuggestScript(char *id, struct slName *suggestList)
 /* Print out a little javascript to wrap auto-suggester around control with given ID */
 {
 printf("<script>\n");
 printf("$(document).ready(function() {\n");
 printf("  $('#%s').autocomplete({\n", id);
 printf("    delay: 100,\n");
 printf("    minLength: 0,\n");
@@ -279,89 +281,81 @@
 
 	char pageVar[64];
 	safef(pageVar, sizeof(pageVar), "%s_page", varPrefix);
 	cgiMakeIntVar(pageVar, curPage+1, 3);
 
 	printf(" of %d", totalPages);
 	}
      }
 }
 
 
 void webFilteredFieldedTable(struct cart *cart, struct fieldedTable *table, 
     char *returnUrl, char *varPrefix,
     int maxLenField, struct hash *tagOutputWrappers, void *wrapperContext,
     boolean withFilters, char *itemPlural, 
-    int pageSize, struct fieldedTableSegment *largerContext, struct hash *suggestHash)
+    int pageSize, struct fieldedTableSegment *largerContext, struct hash *suggestHash, 
+    void (*addFunc)(void) )
 /* Show a fielded table that can be sorted by clicking on column labels and optionally
  * that includes a row of filter controls above the labels .
  * The maxLenField is maximum character length of field before truncation with ...
  * Pass in 0 for no max */
 {
 if (strchr(returnUrl, '?') == NULL)
      errAbort("Expecting returnUrl to include ? in showFieldedTable\nIt's %s", returnUrl);
 
 
 if (withFilters)
-    showTableFilterInstructionsEtc(table, itemPlural, largerContext);
+    showTableFilterInstructionsEtc(table, itemPlural, largerContext, addFunc);
 
 /* Set up our table within table look. */
 webPrintLinkTableStart();
 
 /* Draw optional filters cells ahead of column labels*/
 if (withFilters)
     showTableFilterControlRow(table, cart, varPrefix, maxLenField, suggestHash);
 
 showTableSortingLabelRow(table, cart, varPrefix, returnUrl);
 showTableDataRows(table, pageSize, maxLenField, tagOutputWrappers, wrapperContext);
 
 /* Get rid of table within table look */
 webPrintLinkTableEnd();
 
 if (largerContext != NULL)
     showTablePaging(table, cart, varPrefix, largerContext, pageSize);
 }
 
 void webSortableFieldedTable(struct cart *cart, struct fieldedTable *table, 
     char *returnUrl, char *varPrefix,
     int maxLenField, struct hash *tagOutputWrappers, void *wrapperContext)
 /* Display all of table including a sortable label row.  The tagOutputWrappers
  * is an optional way to enrich output of specific columns of the table.  It is keyed
  * by column name and has for values functions of type webTableOutputWrapperType. */
 {
 webFilteredFieldedTable(cart, table, returnUrl, varPrefix, 
     maxLenField, tagOutputWrappers, wrapperContext,
     FALSE, NULL, 
-    slCount(table->rowList), NULL, NULL);
+    slCount(table->rowList), NULL, NULL, NULL);
 }
 
 
-void webFilteredSqlTable(struct cart *cart, struct sqlConnection *conn, 
-    char *fields, char *from, char *initialWhere,  
-    char *returnUrl, char *varPrefix, int maxFieldWidth, 
-    struct hash *tagOutWrappers, void *wrapperContext,
-    boolean withFilters, char *itemPlural, int pageSize, struct hash *suggestHash)
-/* Given a query to the database in conn that is basically a select query broken into
- * separate clauses, construct and display an HTML table around results. This HTML table has
- * column names that will sort the table, and optionally (if withFilters is set)
- * it will also allow field-by-field wildcard queries on a set of controls it draws above
- * the labels. 
- *    Much of the functionality rests on the call to webFilteredFieldedTable.  This function
- * does the work needed to bring in sections of potentially huge results sets into
- * the fieldedTable. */
+void webTableBuildQuery(struct cart *cart, char *from, char *initialWhere, 
+    char *varPrefix, char *fields, boolean withFilters, 
+    struct dyString **retQuery, struct dyString **retWhere)
+/* Construct select, from and where clauses in query, keeping an additional copy of where 
+ * Returns the SQL query and the SQL where expression as two dyStrings (need to be freed)  */
 {
-/* Construct select, from and where clauses in query, keeping an additional copy of where */
 struct dyString *query = dyStringNew(0);
 struct dyString *where = dyStringNew(0);
 struct slName *field, *fieldList = commaSepToSlNames(fields);
 boolean gotWhere = FALSE;
 sqlDyStringPrintf(query, "%s", ""); // TODO check with Galt on how to get reasonable checking back.
 dyStringPrintf(query, "select %s from %s", fields, from);
 if (!isEmpty(initialWhere))
     {
     dyStringPrintf(where, " where ");
     sqlSanityCheckWhere(initialWhere, where);
     gotWhere = TRUE;
     }
 
 /* If we're doing filters, have to loop through the row of filter controls */
 if (withFilters)
@@ -413,48 +407,71 @@
     }
 dyStringAppend(query, where->string);
 
 /* We do order here so as to keep order when working with tables bigger than a page. */
 char orderVar[256];
 safef(orderVar, sizeof(orderVar), "%s_order", varPrefix);
 char *orderFields = cartUsualString(cart, orderVar, "");
 if (!isEmpty(orderFields))
     {
     if (orderFields[0] == '-')
 	dyStringPrintf(query, " order by %s desc", orderFields+1);
     else
 	dyStringPrintf(query, " order by %s", orderFields);
     }
 
+// return query and where expression
+*retQuery = query;
+*retWhere = where;
+}
+
+void webFilteredSqlTable(struct cart *cart, struct sqlConnection *conn, 
+    char *fields, char *from, char *initialWhere,  
+    char *returnUrl, char *varPrefix, int maxFieldWidth, 
+    struct hash *tagOutWrappers, void *wrapperContext,
+    boolean withFilters, char *itemPlural, int pageSize, struct hash *suggestHash, void (*addFunc)(void) )
+/* Given a query to the database in conn that is basically a select query broken into
+ * separate clauses, construct and display an HTML table around results. This HTML table has
+ * column names that will sort the table, and optionally (if withFilters is set)
+ * it will also allow field-by-field wildcard queries on a set of controls it draws above
+ * the labels. 
+ *    Much of the functionality rests on the call to webFilteredFieldedTable.  This function
+ * does the work needed to bring in sections of potentially huge results sets into
+ * the fieldedTable. */
+{
+struct dyString *query;
+struct dyString *where;
+webTableBuildQuery(cart, from, initialWhere, varPrefix, fields, withFilters, &query, &where);
+
 /* Figure out size of query result */
 struct dyString *countQuery = dyStringNew(0);
 sqlDyStringPrintf(countQuery, "%s", ""); // TODO check with Galt on how to get reasonable checking back.
 dyStringPrintf(countQuery, "select count(*) from %s", from);
 dyStringAppend(countQuery, where->string);
 int resultsSize = sqlQuickNum(conn, countQuery->string);
 dyStringFree(&countQuery);
 
 char pageVar[64];
 safef(pageVar, sizeof(pageVar), "%s_page", varPrefix);
 int page = 0;
 struct fieldedTableSegment context = { .tableSize=resultsSize};
 if (resultsSize > pageSize)
     {
     page = cartUsualInt(cart, pageVar, 0) - 1;
     if (page < 0)
         page = 0;
     int lastPage = (resultsSize-1)/pageSize;
     if (page > lastPage)
         page = lastPage;
     context.tableOffset = page * pageSize;
     dyStringPrintf(query, " limit %d offset %d", pageSize, context.tableOffset);
     }
 
 struct fieldedTable *table = fieldedTableFromDbQuery(conn, query->string);
 webFilteredFieldedTable(cart, table, returnUrl, varPrefix, maxFieldWidth, 
-    tagOutWrappers, wrapperContext, withFilters, itemPlural, pageSize, &context, suggestHash);
+    tagOutWrappers, wrapperContext, withFilters, itemPlural, pageSize, &context, suggestHash, addFunc);
 fieldedTableFree(&table);
 
 dyStringFree(&query);
 dyStringFree(&where);
 }