b8d33c3a3fc4c67dcea6509e744160f8d2c21e7c
tdreszer
Fri Feb 25 12:33:30 2011 -0800
Support for multi-selects for mdb searches on advanced tab. Requires cv.ra change to be active.
diff --git src/hg/hgTracks/searchTracks.c src/hg/hgTracks/searchTracks.c
index 40e6b3d..dabb9f2 100644
--- src/hg/hgTracks/searchTracks.c
+++ src/hg/hgTracks/searchTracks.c
@@ -9,43 +9,47 @@
#include "hash.h"
#include "cheapcgi.h"
#include "hPrint.h"
#include "htmshell.h"
#include "cart.h"
#include "hgTracks.h"
#include "web.h"
#include "jksql.h"
#include "hdb.h"
#include "mdb.h"
#include "fileUi.h"
#include "trix.h"
#include "jsHelper.h"
#include "imageV2.h"
+
#define ANYLABEL "Any"
#define TRACK_SEARCH_FORM "trackSearch"
#define SEARCH_RESULTS_FORM "searchResults"
#define METADATA_NAME_PREFIX "hgt_mdbVar"
#define METADATA_VALUE_PREFIX "hgt_mdbVal"
#define TRACK_SEARCH_CURRENT_TAB "tsCurTab"
#define TRACK_SEARCH_SIMPLE "tsSimple"
#define TRACK_SEARCH_ON_NAME "tsName"
#define TRACK_SEARCH_ON_TYPE "tsType"
#define TRACK_SEARCH_ON_GROUP "tsGroup"
#define TRACK_SEARCH_ON_DESCR "tsDescr"
#define TRACK_SEARCH_SORT "tsSort"
+// If there are problems with multiSelect support, it can quickly be blocked!
+//#define BLOCK_MULTI_SELECT_SUPPORT
+
//#define FILES_SEARCH
#ifdef FILES_SEARCH
#define TRACK_SEARCH_ON_FILETYPE "tsFileType"
#endif///def FILES_SEARCH
// Currently selected tab
enum searchTab {
simpleTab = 0,
advancedTab = 1,
filesTab = 2,
};
static int gCmpGroup(const void *va, const void *vb)
/* Compare groups based on label. */
{
@@ -319,30 +323,31 @@
{
retVar[count] = oneTerm->name;
retLab[count] = oneTerm->val;
count++;
}
}
// Don't do it, unless you clone strings above: slPairFreeValsAndList(&whileList);
*metaVars = retVar;
*metaLabels = retLab;
return count;
}
static int printMdbSelects(struct sqlConnection *conn,struct cart *cart,enum searchTab selectedTab,char ***pMdbVar,char ***pMdbVal,int *numMetadataNonEmpty,int cols)
// Prints a table of mdb selects if appropriate and returns number of them
+// TODO: move to lib since hgTracks and hgFileSearch share it
{
// figure out how many metadata selects are visible.
int delSearchSelect = cartUsualInt(cart, TRACK_SEARCH_DEL_ROW, 0); // 1-based row to delete
int addSearchSelect = cartUsualInt(cart, TRACK_SEARCH_ADD_ROW, 0); // 1-based row to insert after
int numMetadataSelects = 0;
char **mdbVar = NULL;
char **mdbVal = NULL;
char **mdbVars = NULL;
char **mdbVarLabels = NULL;
int i, count = metaDbVars(conn, &mdbVars, &mdbVarLabels);
for(;;)
{
char buf[256];
safef(buf, sizeof(buf), "%s%d", METADATA_NAME_PREFIX, numMetadataSelects + 1);
@@ -376,32 +381,49 @@
else
offset = 1;
safef(buf, sizeof(buf), "%s%d", METADATA_NAME_PREFIX, i + offset);
mdbVar[i] = cloneString(cartOptionalString(cart, buf));
if(selectedTab!=simpleTab)
{
int j;
boolean found = FALSE;
// We need to make sure mdbVar[i] is valid in this assembly; if it isn't, reset it to "cell".
for(j = 0; j < count && !found; j++)
if(sameString(mdbVars[j], mdbVar[i]))
found = TRUE;
if(found)
{
safef(buf, sizeof(buf), "%s%d", METADATA_VALUE_PREFIX, i + offset);
- mdbVal[i] = cloneString(cartOptionalString(cart, buf));
- if(sameString(mdbVal[i], ANYLABEL))
+ enum mdbCvSearchable searchBy = mdbCvSearchMethod(mdbVar[i]);
+ #ifdef BLOCK_MULTI_SELECT_SUPPORT
+ if (searchBy == cvsSearchByMultiSelect) // NOTE: Temprorarily bypass cv.ra
+ searchBy = cvsSearchBySingleSelect;
+ #endif///def BLOCK_MULTI_SELECT_SUPPORT
+ if (searchBy == cvsSearchByMultiSelect)
+ {
+ // Multi-selects as comma delimited list of values
+ struct slName *vals = cartOptionalSlNameList(cart,buf);
+ if (vals)
+ {
+ mdbVal[i] = slNameListToString(vals,','); // A comma delimited list of values
+ slNameFreeList(&vals);
+ }
+ }
+ else
+ mdbVal[i] = cloneString(cartUsualString(cart, buf,ANYLABEL));
+
+ if (mdbVal[i] != NULL && sameString(mdbVal[i], ANYLABEL))
mdbVal[i] = NULL;
}
else
{
mdbVar[i] = cloneString("cell");
mdbVal[i] = NULL;
}
if(!isEmpty(mdbVal[i]))
(*numMetadataNonEmpty)++;
}
}
if(delSearchSelect > 0)
{
char buf[255];
safef(buf, sizeof(buf), "%s%d", METADATA_NAME_PREFIX, numMetadataSelects + 1);
@@ -410,94 +432,99 @@
cartRemove(cart, buf);
}
}
else
{
// create defaults
numMetadataSelects = 2;
mdbVar = needMem(sizeof(char *) * numMetadataSelects);
mdbVal = needMem(sizeof(char *) * numMetadataSelects);
mdbVar[0] = "cell";
mdbVar[1] = "antibody";
mdbVal[0] = ANYLABEL;
mdbVal[1] = ANYLABEL;
}
- hPrintf("
ENCODE terms ", cols,COLOR_DARKGREY);
+ hPrintf("ENCODE terms \n", cols,COLOR_DARKGREY);
for(i = 0; i < numMetadataSelects; i++)
{
char **terms = NULL, **labels = NULL;
char buf[256];
int len;
#define PLUS_MINUS_BUTTON " "
- #define PRINT_PM_BUTTON(type,num,value) printf(PLUS_MINUS_BUTTON, (type), (num), (value), ((value) == '+' ? "add another row after":"delete"), (num));
- #ifndef PLUS_MINUS_BUTTON
- #define PRINT_BUTTON(name,value,msg,js) printf(" ", (name), (value), (msg), (js));
- #endif//ndef PLUS_MINUS_BUTTON
- hPrintf("\n");
+ #define PRINT_PM_BUTTON(type,num,value) printf(PLUS_MINUS_BUTTON, (type), (num), (value), ((value) == '+' ? "add another row after":"delete"), (num))
+ hPrintf(" \n");
if(numMetadataSelects > 2 || i >= 2)
- {
- #ifdef PLUS_MINUS_BUTTON
PRINT_PM_BUTTON("minus", i + 1, '-');
- #else///ifndef PLUS_MINUS_BUTTON
- safef(buf, sizeof(buf), "return delSearchSelect(this, %d);", i + 1);
- PRINT_BUTTON(TRACK_SEARCH, "-", "delete this row", buf);
- #endif//ndef PLUS_MINUS_BUTTON
- }
else
hPrintf(" ");
- #ifdef PLUS_MINUS_BUTTON
PRINT_PM_BUTTON("plus", i + 1, '+');
- #else///ifndef PLUS_MINUS_BUTTON
- hPrintf(" \n");
- safef(buf, sizeof(buf), "return addSearchSelect(this, %d);", i + 1);
- PRINT_BUTTON(TRACK_SEARCH, "+", "add another row after this row", buf);
- #endif//ndef PLUS_MINUS_BUTTON
hPrintf(" and \n");
safef(buf, sizeof(buf), "%s%i", METADATA_NAME_PREFIX, i + 1);
- cgiDropDownWithTextValsAndExtra(buf, mdbVarLabels, mdbVars,count,mdbVar[i],"class='mdbVar' style='font-size:.9em;' onchange='findTracksMdbVarChanged(this);'");
- // TODO: move to lib since hgTracks and hgApi share
enum mdbCvSearchable searchBy = mdbCvSearchMethod(mdbVar[i]);
+ #ifdef BLOCK_MULTI_SELECT_SUPPORT
+ if (searchBy == cvsSearchByMultiSelect) // NOTE: Temprorarily bypass cv.ra
+ searchBy = cvsSearchBySingleSelect;
+ #else///ndef BLOCK_MULTI_SELECT_SUPPORT
+ cgiDropDownWithTextValsAndExtra(buf, mdbVarLabels, mdbVars,count,mdbVar[i],"class='mdbVar' style='font-size:.9em;' onchange='findTracksMdbVarChanged(this);'");
+ safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1);
+ #endif///ndef BLOCK_MULTI_SELECT_SUPPORT
if (searchBy == cvsSearchByMultiSelect)
{
- // TO BE IMPLEMENTED
+ #ifdef BLOCK_MULTI_SELECT_SUPPORT
+ cgiDropDownWithTextValsAndExtra(buf, mdbVarLabels, mdbVars,count,mdbVar[i],"class='mdbVar' style='font-size:.9em;' onchange='findTracksMdbVarChanged(this);'");
+ safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1);
+ #endif///ndef BLOCK_MULTI_SELECT_SUPPORT
+ printf(" \nis (any of) \n\n",i + 1,buf);
+ #define MULTI_SELECT_CBS_FORMAT "\n"
+ printf(MULTI_SELECT_CBS_FORMAT,buf);
+ len = getTermArray(conn, &labels, &terms, mdbVar[i]);
+ int tix=0;
+ for(;tix < len;tix++)
+ {
+ char *selected = findWordByDelimiter(terms[tix],',', mdbVal[i]);
+ printf("%s \n",(selected != NULL?" SELECTED":""),terms[tix],labels[tix]);
+ }
+ printf(" \n");
}
else if (searchBy == cvsSearchBySingleSelect)
{
+ #ifdef BLOCK_MULTI_SELECT_SUPPORT
+ cgiDropDownWithTextValsAndExtra(buf, mdbVarLabels, mdbVars,count,mdbVar[i],"class='mdbVar noMulti' style='font-size:.9em;' onchange='findTracksMdbVarChanged(this);'");
safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1);
- hPrintf(" is \n",i + 1,buf);
+ #endif///ndef BLOCK_MULTI_SELECT_SUPPORT
+ hPrintf(" \nis \n\n",i + 1,buf);
len = getTermArray(conn, &labels, &terms, mdbVar[i]);
- #ifdef PLUS_MINUS_BUTTON
- cgiMakeDropListFull(buf, labels, terms, len, mdbVal[i], "class='mdbVal single' style='min-width:200px; font-size:.9em;' onchange='findTracksMdbValChanged(this);'");
- #else///ifndef PLUS_MINUS_BUTTON
- cgiMakeDropListFull(buf, labels, terms, len, mdbVal[i], "class='mdbVal single' style='min-width:200px; font-size:.9em;' onchange='findTracksSearchButtonsEnable(true);'");
- #endif//ndef PLUS_MINUS_BUTTON
+ cgiMakeDropListFull(buf, labels, terms, len, mdbVal[i], "class='mdbVal' style='min-width:200px; font-size:.9em;' onchange='findTracksMdbValChanged(this);'");
}
else if (searchBy == cvsSearchByFreeText)
{
+ #ifdef BLOCK_MULTI_SELECT_SUPPORT
+ cgiDropDownWithTextValsAndExtra(buf, mdbVarLabels, mdbVars,count,mdbVar[i],"class='mdbVar noMulti' style='font-size:.9em;' onchange='findTracksMdbVarChanged(this);'");
safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1);
- hPrintf(" contains \n",i + 1,buf);
- hPrintf(" ",
+ #endif///ndef BLOCK_MULTI_SELECT_SUPPORT
+ hPrintf(" contains \n\n",i + 1,buf);
+ hPrintf(" \n",
buf,(mdbVal[i] ? mdbVal[i]: ""));
}
else if (searchBy == cvsSearchByDateRange || searchBy == cvsSearchByIntegerRange)
{
// TO BE IMPLEMENTED
}
- hPrintf("help \n", i + 1);
+ hPrintf(" \n", i + 1);
hPrintf(" \n");
}
hPrintf(" ", cols);
//hPrintf(" ", cols);
return numMetadataSelects;
}
static struct slRef *simpleSearchForTracksstruct(struct trix *trix,char **descWords,int descWordCount)
// Performs the simple search and returns the found tracks.
{
struct slRef *tracks = NULL;
struct trixSearchResult *tsList;
@@ -835,30 +862,39 @@
"Look and feel of found track list (here) and composite subtrack list (hgTrackUi) should converge. Jim suggests look and feel of hgTracks 'Configure Tracks...' list instead. "
"Drop-down list of terms (cells, antibodies, etc.) should be multi-select with checkBoxes as seen in filterComposites. Perhaps saved for v2.0. "
"\n");
}
#endif///def OMIT
hPrintf(""); // This div allows the clear button to empty it
}
void doSearchTracks(struct group *groupList)
{
if (!advancedJavascriptFeaturesEnabled(cart))
{
warn("Requires advanced javascript features.");
return;
}
+
+#ifndef BLOCK_MULTI_SELECT_SUPPORT
+webIncludeResourceFile("ui.dropdownchecklist.css");
+//jsIncludeFile("ui.core.js",NULL); // NOTE: This appears to be not needed as long as jquery-ui.js comes before ui.dropdownchecklist.js
+jsIncludeFile("ui.dropdownchecklist.js",NULL);
+// This line is needed to get the multi-selects initialized
+hPrintf("\n");
+#endif///ndef BLOCK_MULTI_SELECT_SUPPORT
+
struct group *group;
char *groups[128];
char *labels[128];
int numGroups = 1;
groups[0] = ANYLABEL;
labels[0] = ANYLABEL;
char *nameSearch = cartOptionalString(cart, TRACK_SEARCH_ON_NAME);
char *typeSearch = cartOptionalString(cart, TRACK_SEARCH_ON_TYPE);
#ifdef FILES_SEARCH
char *fileTypeSearch = cartOptionalString(cart, TRACK_SEARCH_ON_FILETYPE);
#endif///def FILES_SEARCH
char *descSearch=FALSE;
char *groupSearch = cartOptionalString(cart, TRACK_SEARCH_ON_GROUP);
boolean doSearch = sameString(cartOptionalString(cart, TRACK_SEARCH), "Search") || cartUsualInt(cart, TRACK_SEARCH_PAGER, -1) >= 0;
struct sqlConnection *conn = hAllocConn(database);