ddeedc6ab30032756ea7ccddabec70f01357d035 tdreszer Wed Sep 22 09:45:43 2010 -0700 Reformatted tabs and added search toggle diff --git src/hg/hgTracks/searchTracks.c src/hg/hgTracks/searchTracks.c index 902efd5..4cde524 100644 --- src/hg/hgTracks/searchTracks.c +++ src/hg/hgTracks/searchTracks.c @@ -33,6 +33,35 @@ return strcmp(a->label, b->label); } +// Would like to do a radio button choice ofsorts +#define SORT_BY_HIERARCHY +#ifdef SORT_BY_HIERARCHY +#define SORT_BY_VAR "findTracksSortBy" +#define SORT_BY_ABC "abc" +#define SORT_BY_HIER "hier" +static int gCmpTrackHierarchy(const void *va, const void *vb) +/* Compare tracks based on longLabel. */ +{ +const struct slRef *aa = *((struct slRef **)va); +const struct slRef *bb = *((struct slRef **)vb); +const struct track *a = ((struct track *) aa->val); +const struct track *b = ((struct track *) bb->val); + if ( tdbIsSuperTrack(a->tdb) && !tdbIsSuperTrack(b->tdb)) + return -1; +else if (!tdbIsSuperTrack(a->tdb) && tdbIsSuperTrack(b->tdb)) + return 1; + if ( tdbIsComposite(a->tdb) && !tdbIsComposite(b->tdb)) + return -1; +else if (!tdbIsComposite(a->tdb) && tdbIsComposite(b->tdb)) + return 1; + if (!tdbIsCompositeChild(a->tdb) && tdbIsCompositeChild(b->tdb)) + return -1; +else if ( tdbIsCompositeChild(a->tdb) && !tdbIsCompositeChild(b->tdb)) + return 1; +return strcasecmp(a->longLabel, b->longLabel); +} +#endif///def SORT_BY_HIERARCHY + static int gCmpTrack(const void *va, const void *vb) /* Compare tracks based on longLabel. */ { @@ -40,7 +69,7 @@ const struct slRef *bb = *((struct slRef **)vb); const struct track *a = ((struct track *) aa->val); const struct track *b = ((struct track *) bb->val); -return strcmp(a->longLabel, b->longLabel); +return strcasecmp(a->longLabel, b->longLabel); } // XXXX make a matchString function to support "contains", "is" etc. and wildcards in contains @@ -306,6 +335,7 @@ webStartWrapperDetailedNoArgs(cart, database, "", "Search for Tracks", FALSE, FALSE, FALSE, FALSE); +hPrintf("<div style='max-width:1000px'>"); hPrintf("<form action='%s' name='SearchTracks' id='searchTracks' method='get'>\n\n", hgTracksName()); cartSaveSession(cart); // Creates hidden var of hgsid to avoid bad voodoo @@ -315,15 +345,15 @@ hPrintf("<input type='hidden' name='hgt.addRow' value=''>\n"); hPrintf("<input type='hidden' name='hgt.forceSearch' value=''>\n"); -hPrintf("<div id='tabs' style='display:none;'>\n" +hPrintf("<div id='tabs' style='display:none; width:inherit'>\n" "<ul>\n" "<li><a href='#simpleTab'><span>Search</span></a></li>\n" - "<li><a href='#advancedTab'><span>Advanced <em>- by %sterms</em></span></a></li>\n" + "<li><a href='#advancedTab'><span>Advanced</span></a></li>\n" "</ul>\n" - "<div id='simpleTab'>\n",metaDbExists?"ENCODE ":""); + "<div id='simpleTab' style='width:inherit;'>\n"); -hPrintf("<table><tr><td colspan='2'>"); -hPrintf("<input type='text' name='hgt.simpleSearch' id='simpleSearch' value='%s' size='80' onkeyup='findTracksSearchButtonsEnable(true);'>\n", descSearch == NULL ? "" : descSearch); +hPrintf("<table style='width:100%%;'><tr><td colspan='2'>"); +hPrintf("<input type='text' name='hgt.simpleSearch' id='simpleSearch' value='%s' style='width:100%%' onkeyup='findTracksSearchButtonsEnable(true);'>\n", descSearch == NULL ? "" : descSearch); hPrintf("</td></tr><tr><td>"); if (simpleSearch && descSearch) searchTermsExist = TRUE; @@ -331,28 +361,39 @@ hPrintf("<input type='submit' name='%s' id='searchSubmit' value='Search' style='font-size:14px;'>\n", searchTracks); hPrintf("<input type='button' name='clear' value='Clear' class='clear' style='font-size:14px;' onclick='findTracksClear();'>\n"); hPrintf("<input type='submit' name='submit' value='Cancel' class='cancel' style='font-size:14px;'>\n"); -hPrintf("</td><td align='right'><a target='_blank' href='../goldenPath/help/trackSearch.html'>help</a></td></tr></table>\n"); +hPrintf("<a target='_blank' href='../goldenPath/help/trackSearch.html'>help</a></td></tr></table>\n"); +//hPrintf("</td><td align='right'><a target='_blank' href='../goldenPath/help/trackSearch.html'>help</a></td></tr></table>\n"); hPrintf("</div>\n" "<div id='advancedTab'>\n" - "<table>\n"); - -hPrintf("<tr><td></td><td></td><td></td><td><b>Track Name:</b></td><td align='right'>contains</td>\n"); -//char *ops[] = {"is", "contains"}; -//char *op_labels[] = {"is", "contains"}; -//char *nameOp = cartOptionalString(cart, "hgt.nameOp"); -//cgiMakeDropListFull("hgt.nameOp", op_labels, ops, ArraySize(ops), nameOp == NULL ? "contains" : nameOp, NULL); -hPrintf("</td>\n<td><input type='text' name='hgt.nameSearch' id='nameSearch' value='%s' onkeyup='findTracksSearchButtonsEnable(true);'></td></tr>\n", nameSearch == NULL ? "" : nameSearch); + "<table cellSpacing=0 style='width:100%%;'>\n"); + +// Track Name contains +hPrintf("<tr><td colspan=3 style='width:5%%;'></td>"); +hPrintf("<td style='width:10px;' nowrap><b>Track Name:</b></td>"); +hPrintf("<td align='right' style='width:10px;'>contains</td>\n"); +hPrintf("<td colspan=3>"); +hPrintf("<input type='text' name='hgt.nameSearch' id='nameSearch' value='%s' onkeyup='findTracksSearchButtonsEnable(true);' style='min-width:326px;'>", nameSearch == NULL ? "" : nameSearch); +hPrintf("</td></tr>\n"); if (!simpleSearch && nameSearch) searchTermsExist = TRUE; -hPrintf("<tr><td></td><td></td><td>and</td><td><b>Description:</b></td><td align='right'>contains</td>\n"); -hPrintf("<td><input type='text' name='hgt.descSearch' id='descSearch' value='%s' size='80' onkeyup='findTracksSearchButtonsEnable(true);'></td></tr>\n", descSearch == NULL ? "" : descSearch); +// Description contains +hPrintf("<tr><td colspan=2 style='width:2%%;'></td><td style='width:2%%;'>and </td>"); +hPrintf("<td style='width:10px;'><b>Description:</b></td>"); +hPrintf("<td align='right' style='width:10px;'>contains</td>\n"); +hPrintf("<td colspan=3>"); +hPrintf("<input type='text' name='hgt.descSearch' id='descSearch' value='%s' onkeyup='findTracksSearchButtonsEnable(true);' style='min-width:100%%;'>", + descSearch == NULL ? "" : descSearch); +hPrintf("</td></tr>\n"); if (!simpleSearch && descSearch) searchTermsExist = TRUE; -hPrintf("<tr><td></td><td></td><td>and</td>\n"); -hPrintf("<td><b>Group</b></td><td align='right'>is</td>\n<td>\n"); -cgiMakeDropListFull("hgt.groupSearch", labels, groups, numGroups, groupSearch, "class='groupSearch'"); +// Group is +hPrintf("<tr><td colspan=2 style='width:2%%;'></td><td style='width:2%%;'>and </td>\n"); +hPrintf("<td style='width:10px;'><b>Group</b></td>"); +hPrintf("<td align='right' style='width:10px;'>is</td>\n"); +hPrintf("<td colspan=3>"); +cgiMakeDropListFull("hgt.groupSearch", labels, groups, numGroups, groupSearch, "class='groupSearch' style='min-width:40%%;'"); hPrintf("</td></tr>\n"); if (!simpleSearch && groupSearch) searchTermsExist = TRUE; @@ -433,13 +474,14 @@ char **mdbVarLabels = NULL; int count = metaDbVars(conn, &mdbVars,&mdbVarLabels); + hPrintf("<tr cellpadding=0><td colspan=10 class='lineOnBottom' style='height:2px; max-height:2px;'> </td></tr>"); for(i = 0; i < numMetadataSelects; i++) { char **terms; char buf[256]; int len; - hPrintf("<tr><td>\n"); + hPrintf("<tr><td style='width:2%%;'>\n"); if(numMetadataSelects > 2 || i >= 2) { safef(buf, sizeof(buf), "return delSearchSelect(this, %d);", i + 1); @@ -447,34 +489,34 @@ } else hPrintf(" "); - hPrintf("</td><td>\n"); + hPrintf("</td><td style='width:2%%;'>\n"); safef(buf, sizeof(buf), "return addSearchSelect(this, %d);", i + 1); hButtonWithOnClick(searchTracks, "+", "add another row after this row", buf); - hPrintf("</td><td>and</td>\n"); - hPrintf("</td><td colspan=2 nowrap>\n"); + hPrintf("</td><td style='width:2%%;'>and </td><td colspan=3 nowrap style='width:10%%;'>\n"); safef(buf, sizeof(buf), "%s%i", METADATA_NAME_PREFIX, i + 1); cgiDropDownWithTextValsAndExtra(buf, mdbVarLabels, mdbVars,count,mdbVar[i],"class='mdbVar' onchange=findTracksMdbVarChanged(this)"); - //cgiMakeDropListClassWithStyleAndJavascript(buf, mdbVars, count, mdbVar[i], - // "mdbVar", NULL, "onchange=findTracksMdbVarChanged(this)"); - hPrintf("is</td>\n<td>\n"); + hPrintf("</td><td%s>is\n",(i == 0 ? "":" colspan=2")); len = getTermArray(conn, &terms, mdbVar[i]); safef(buf, sizeof(buf), "%s%i", METADATA_VALUE_PREFIX, i + 1); - cgiMakeDropListFull(buf, terms, terms, len, mdbVal[i], "class='mdbVal' onchange='findTracksSearchButtonsEnable(true)'"); + cgiMakeDropListFull(buf, terms, terms, len, mdbVal[i], "class='mdbVal' style='max-width:520px; min-width:200px;' onchange='findTracksSearchButtonsEnable(true)'"); if (!simpleSearch && mdbVal[i]) searchTermsExist = TRUE; + if (i == 0) + hPrintf("</td><td align='right' valign='top' nowrap><em style='color:%s'>ENCODE terms</em>",COLOR_DARKGREY); hPrintf("</td></tr>\n"); } } -hPrintf("<tr><td colspan='5'>\n"); +hPrintf("<tr><td colspan='10'>\n"); hPrintf("<input type='submit' name='%s' id='searchSubmit' value='Search' style='font-size:14px;'>\n", searchTracks); hPrintf("<input type='button' name='clear' value='Clear' class='clear' style='font-size:14px;' onclick='findTracksClear();'>\n"); hPrintf("<input type='submit' name='submit' value='Cancel' class='cancel' style='font-size:14px;'>\n"); -hPrintf("</td><td align='left'><a target='_blank' href='../goldenPath/help/trackSearch.html'>help</a></td></tr>\n"); +hPrintf("<a target='_blank' href='../goldenPath/help/trackSearch.html'>help</a></td></tr>\n"); hPrintf("</table>\n"); hPrintf("</div>\n</div>\n"); hPrintf("</form>\n"); +hPrintf("</div"); // Restricts to max-width:1000px; if(descSearch != NULL && !strlen(descSearch)) descSearch = NULL; @@ -498,6 +540,9 @@ descWords[i] = strLower(el->name); } +#ifdef SORT_BY_HIERARCHY +boolean sortByHierarchy = sameString(cartUsualString(cart,SORT_BY_VAR,SORT_BY_HIER),SORT_BY_HIER); +#endif///def SORT_BY_HIERARCHY if(doSearch) { if(simpleSearch) @@ -529,7 +574,11 @@ //else // FIXME: Should get to the bottom of why some of these are null // warn("found trix track is NULL."); } + #ifdef SORT_BY_HIERARCHY + slSort(&tracks, sortByHierarchy? gCmpTrackHierarchy:gCmpTrack); + #else///ifndef SORT_BY_HIERARCHY slReverse(&tracks); + #endif///ndef SORT_BY_HIERARCHY } else if(!isEmpty(nameSearch) || descSearch != NULL || groupSearch != NULL || numMetadataNonEmpty) { @@ -616,7 +665,11 @@ } } } + #ifdef SORT_BY_HIERARCHY + slSort(&tracks, sortByHierarchy? gCmpTrackHierarchy:gCmpTrack); + #else///ifndef SORT_BY_HIERARCHY slSort(&tracks, gCmpTrack); + #endif///ndef SORT_BY_HIERARCHY } } @@ -652,10 +705,20 @@ hPrintf("</td><td align='right'>\n"); #define PM_BUTTON "<IMG height=18 width=18 onclick=\"return findTracksCheckAllWithWait(%s);\" id='btn_%s' src='../images/%s' title='%s all found tracks'>" hPrintf("</td></tr><tr bgcolor='#%s'><td>",HG_COL_HEADER); - printf(PM_BUTTON,"true", "plus_all", "add_sm.gif", "Select"); - printf(PM_BUTTON,"false","minus_all","remove_sm.gif","Unselect"); - hPrintf("</td><td><b>Visibility</b></td><td colspan=2> <b>Track Name</b></td></tr>\n"); - // FIXME: I believe that only data tracks should appear in found tracks. If composite is found, show its children instead + hPrintf(PM_BUTTON,"true", "plus_all", "add_sm.gif", "Select"); + hPrintf(PM_BUTTON,"false","minus_all","remove_sm.gif","Unselect"); + hPrintf("</td><td><b>Visibility</b></td><td colspan=2> <b>Track Name</b>\n"); + if(tracksFound >= ENOUGH_FOUND_TRACKS) + { + #ifdef SORT_BY_HIERARCHY + hPrintf("<span style='float:right;'>Sort:"); + cgiMakeOnClickRadioButton(SORT_BY_VAR, SORT_BY_ABC, !sortByHierarchy,"onchange=\"findTracksSortNow(this);\""); // FIXME: var is in wrong form! + hPrintf("Alphabetically"); + cgiMakeOnClickRadioButton(SORT_BY_VAR, SORT_BY_HIER,sortByHierarchy, "onchange=\"findTracksSortNow(this);\""); + hPrintf("by Hierarchy </span>\n"); + #endif///def SORT_BY_HIERARCHY + } + hPrintf("</td></tr>\n"); int trackCount=0; boolean containerTrackCount = 0; @@ -668,7 +731,14 @@ struct track *track = (struct track *) ptr->val; jsonTdbSettingsBuild(&jsonTdbVars, track); - hPrintf("<tr bgcolor='%s' valign='top' class='found'>\n",COLOR_BG_ALTDEFAULT); + #ifdef SORT_BY_HIERARCHY + if (tdbIsSuperTrack(track->tdb)) + hPrintf("<tr bgcolor='%s' valign='top' class='found'>\n",COLOR_TRACKLIST_LEVEL1); + if (tdbIsComposite(track->tdb)) + hPrintf("<tr bgcolor='%s' valign='top' class='found'>\n",COLOR_TRACKLIST_LEVEL3); + else + #endif///def SORT_BY_HIERARCHY + hPrintf("<tr bgcolor='%s' valign='top' class='found'>\n",COLOR_TRACKLIST_LEVEL2); hPrintf("<td align='center' valign='center'>\n"); char name[256]; @@ -740,26 +810,24 @@ hWrites(jsonTdbSettingsUse(&jsonTdbVars)); } +if(!doSearch) + { hPrintf("<p><b>Recently Done</b><ul>\n" + #ifdef SORT_BY_HIERARCHY + "<li>Added sort toggle: Alphabetically or by Hierarchy.</li>" + #endif///def SORT_BY_HIERARCHY "<li>Composite/view visibilites in hgTrackUi get reshaped to reflect found/selected subtracks. (In demo1: only default state composites; demo2: all composites.)</li>" "<li>Metadata variables have been 'white-listed' to only include vetted items. Short text descriptions and vetted list should be reviewed.</li>" "<li>Clicking on shortLabel for found track will popup the description text. Subtracks should show their composite description.</li>" "<li>Non-data 'container' tracks (composites and supertracks) have '*' to mark them, and can be configured before displaying. Better suggestions?</li>" - "<li>Simple search should now query metaDb properly (and included descriptions for cv terms like 'cell'). This had been failing earlier.</li>" - "<li>Short and long label searched on advanced 'Track Name' search.</li>" "<li>Found track list shows only the first 100 tracks with warning to narrow search. Larry suggests this could be done by pages of results in v2.0.</li>\n" "</ul></p>" - "<p><b>Known Problems</b><ul>" - "<li>Strangeness seen in finding tracks: 'ENCODE' in description combined with antibody selection results in no tracks found." - "<BR>QUESTION: Is that a bug? REM that description search is NOT inherited. (* Suggestions below.)</li>" - "</ul></p>" "<p><b>Suggested improvments:</b><ul>\n" "<li>The metadata values will not be white-listed, but it would be nice to have more descriptive text for them. A short label added to cv.ra?</li>" "<li>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.</li>" "<li>Drop-down list of terms (cells, antibodies, etc.) should be multi-select with checkBoxes as seen in filterComposites. Perhaps saved for v2.0.</li>" - "<li>* 'Descrtiption' should be inherited by subtracks?</li>" "</ul></p>\n"); - + } hPrintf("</div"); // This div allows the clear button to empty it webEndSectionTables(); }