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"); } 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);