4c389c37d5a42eafb281c81ca6d12271a58f1499 jcasper Thu Jun 22 13:18:03 2017 -0700 hgHubConnect now expands on single click, show results in correct order, and has more intuitive logic for the search/filter text boxes, refs #13625 diff --git src/hg/hgHubConnect/hgHubConnect.c src/hg/hgHubConnect/hgHubConnect.c index 6a7c49c..4a1fabe 100644 --- src/hg/hgHubConnect/hgHubConnect.c +++ src/hg/hgHubConnect/hgHubConnect.c @@ -398,74 +398,84 @@ } else { // no db in the hubSearchText means this is a top-level hub hit. // filter by the db list associated with the hub instead struct hubEntry *hubInfo = hashFindVal(hubLookup, hubUrl); char *dbList = cloneString(hubInfo->dbList); tolowers(dbList); if (stringIn(dbFilter, dbList) == NULL) continue; } } // Add hst to the list to be returned slAddHead(&hubSearchResultsList, hst); } +slReverse(&hubSearchResultsList); return hubSearchResultsList; } -void printSearchBox(char *hubSearchTerms, char *dbFilter) +void printSearchAndFilterBoxes(int searchEnabled, char *hubSearchTerms, char *dbFilter) /* Create the text boxes for search and database filtering along with the required * javscript */ { +char event[4096]; +if (searchEnabled) + { + safef(event, sizeof(event), + "document.searchHubForm.elements['hubSearchTerms'].value=$('#hubSearchTerms').val();" + "document.searchHubForm.elements['hubDbFilter'].value=$('#hubDbFilter').val();" + "document.searchHubForm.submit();return true;"); printf("Enter search terms to find in public track hub description pages:<BR>" "<input name=\"hubSearchTerms\" id=\"hubSearchTerms\" class=\"hubField\" " - "type=\"text\" size=\"65\" value=\"%s\"> \n" - "<input name=\"hubSearchButton\" id='hubSearchButton' " - "class=\"hubField\" type=\"button\" value=\"Search Public Hubs\">\n", + "type=\"text\" size=\"65\" value=\"%s\"> \n", hubSearchTerms!=NULL?hubSearchTerms:""); -jsOnEventById("click", "hubSearchButton", - "document.searchHubForm.elements['hubSearchTerms'].value=$('#hubSearchTerms').val();" - "document.searchHubForm.submit();return true;"); printf("<br>\n"); + } +else + { + safef(event, sizeof(event), + "document.searchHubForm.elements['hubDbFilter'].value=$('#hubDbFilter').val();" + "document.searchHubForm.submit();return true;"); + } + printf("Filter hubs by assembly: " "<input name=\"%s\" id=\"hubDbFilter\" class=\"hubField\" " "type=\"text\" size=\"10\" value=\"%s\"> \n" - "<input name=\"dbFilterButton\" id='dbFilterButton' " - "class=\"hubField\" type=\"button\" value=\"Filter assemblies\">\n", + "<input name=\"hubSearchButton\" id='hubSearchButton' " + "class=\"hubField\" type=\"button\" value=\"Search Public Hubs\">\n", hgHubDbFilter, dbFilter!=NULL?dbFilter:""); -jsOnEventById("click", "dbFilterButton", - "document.dbFilterHubForm.elements['hubDbFilter'].value=$('#hubDbFilter').val();" - "document.dbFilterHubForm.submit();return true;"); -puts("<BR><BR>\n"); +jsOnEventById("click", "hubSearchButton", event); +puts("<br><br>\n"); } void printSearchTerms(char *hubSearchTerms) /* Write out a reminder about the current search terms and a note about * how to navigate detailed search results */ { printf("Displayed list <B>restricted by search terms:</B> %s\n", hubSearchTerms); puts("<input name=\"hubDeleteSearchButton\" id='hubDeleteSearchButton' " "class=\"hubField\" type=\"button\" value=\"Show All Hubs\">\n"); jsOnEventById("click", "hubDeleteSearchButton", "document.searchHubForm.elements['hubSearchTerms'].value='';" + "document.searchHubForm.elements['hubDbFilter'].value='';" "document.searchHubForm.submit();return true;"); puts("<BR><BR>\n"); printf("When exploring the detailed search results for a hub, you may right-click " - "on an assembly or track line to open it in a new window\n"); + "on an assembly or track line to open it in a new window.\n"); puts("<BR><BR>\n"); } void printHubListHeader() /* Write out the header for a list of hubs in its own table */ { puts("<I>Clicking Connect redirects to the gateway page of the selected hub's default assembly.</I><BR>"); printf("<table id=\"publicHubsTable\" class=\"hubList\"> " "<thead><tr> " "<th>Display</th> " "<th>Hub Name</th> " "<th>Description</th> " "<th>Assemblies</th> " "</tr></thead></table>\n"); @@ -950,32 +960,32 @@ char *dbFilter = cartOptionalString(cart, hgHubDbFilter); char *lcDbFilter = cloneString(dbFilter); if (isNotEmpty(lcDbFilter)) tolowers(lcDbFilter); // make sure all the public hubs are in the hubStatus table. addPublicHubsToHubStatus(conn, publicTable, statusTable); // build full public hub lookup hash, taking each URL to struct hubEntry * for that hub struct hash *hubLookup = buildPublicLookupHash(conn, publicTable, statusTable, pHash); printf("<div id=\"publicHubs\" class=\"hubList\"> \n"); char *hubSearchTableName = cfgOptionDefault("hubSearchTextTable", "hubSearchText"); int searchEnabled = sqlTableExists(conn, hubSearchTableName); -if (searchEnabled) - printSearchBox(hubSearchTerms, dbFilter); + +printSearchAndFilterBoxes(searchEnabled, hubSearchTerms, dbFilter); struct hash *searchResultHash = NULL; struct slName *hubsToPrint = NULL; if (searchEnabled && !isEmpty(hubSearchTerms)) { printSearchTerms(hubSearchTerms); if (isNotEmpty(cleanSearchTerms)) tolowers(cleanSearchTerms); // Forcing checkDescriptions to TRUE right now, but we might want to add this as a // checkbox option for users in the near future. bool checkDescriptions = TRUE; struct hubSearchText *hubSearchResults = getHubSearchResults(conn, hubSearchTableName, cleanSearchTerms, checkDescriptions, lcDbFilter, hubLookup); searchResultHash = newHash(5); struct hubSearchText *hst = hubSearchResults; @@ -1259,100 +1269,100 @@ cgiMakeHiddenVar(hgHubDoDisconnect, "on"); cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on"); cartSaveSession(cart); puts("</FORM>"); // this is the form for the reset hub button printf("<FORM ACTION=\"%s\" NAME=\"resetHubForm\">\n", "../cgi-bin/hgHubConnect"); cgiMakeHiddenVar(hgHubCheckUrl, ""); cartSaveSession(cart); puts("</FORM>"); // this is the form for the search hub button printf("<FORM ACTION=\"%s\" NAME=\"searchHubForm\">\n", "../cgi-bin/hgHubConnect"); cgiMakeHiddenVar(hgHubSearchTerms, ""); cgiMakeHiddenVar(hgHubDoSearch, "on"); -cartSaveSession(cart); -puts("</FORM>"); - -// this is the form for the search hub button -printf("<FORM ACTION=\"%s\" NAME=\"dbFilterHubForm\">\n", "../cgi-bin/hgHubConnect"); cgiMakeHiddenVar(hgHubDbFilter, ""); -cgiMakeHiddenVar(hgHubDoFilter, "on"); cartSaveSession(cart); puts("</FORM>"); // ... and now the main form printf("<FORM ACTION=\"%s\" METHOD=\"POST\" NAME=\"mainForm\">\n", "../cgi-bin/hgGateway"); cartSaveSession(cart); // we have two tabs for the public and unlisted hubs printf("<div id=\"tabs\">" "<ul> <li><a href=\"#publicHubs\">Public Hubs</a></li>" "<li><a href=\"#unlistedHubs\">My Hubs</a></li> " "</ul> "); struct hash *publicHash = hgHubConnectPublic(); hgHubConnectUnlisted(hubList, publicHash); printf("</div>"); printf("<div class=\"tabFooter\">"); -char *emailAddress = cfgOptionDefault("hub.emailAddress","genome@soe.ucsc.edu"); printf("<span class=\"small\">" - "Contact <A HREF=\"mailto:%s\">%s</A> to add a public hub." - "</span>\n", emailAddress,emailAddress); + "Contact <a href=\"../contacts.html\">us</A> to add a public hub." + "</span>\n"); printf("</div>"); cgiMakeHiddenVar(hgHubConnectRemakeTrackHub, "on"); puts("</FORM>"); printf("</div>\n"); jsInline( "var hubSearchTree = (function() {\n" " // Effectively global vars set by init\n" " var treeDiv; // Points to div we live in\n" "\n" " function hubSearchTreeContextMenuHandler (node, callback) {\n" " var nodeType = node.li_attr.nodetype;\n" " if (nodeType == 'track') {\n" " callback({\n" " 'openConfig': {\n" " 'label' : 'Configure this track',\n" " 'action' : function () {window.open(node.li_attr.configlink, '_blank'); }\n" " }\n" " });\n" " }\n" " else if (nodeType == 'assembly') {\n" " callback({\n" " 'openConfig': {\n" " 'label' : 'Open this assembly',\n" " 'action' : function () {window.open(node.li_attr.assemblylink, '_blank'); }\n" " }\n" " });\n" " }\n" -" }" +" }\n" +" function toggleExpansion(node, event) {\n" +" var ident = '#' + node.id;\n" +" if (event.type != 'contextmenu')\n" +" $(ident).jstree(true).toggle_node(node);\n" +" return false;\n" +" }\n" " function init() {\n" " $.jstree.defaults.core.themes.icons = false;\n" " $.jstree.defaults.core.themes.dots = true;\n" " $.jstree.defaults.contextmenu.show_at_node = false;\n" " $.jstree.defaults.contextmenu.items = hubSearchTreeContextMenuHandler\n" " treeDiv=$('.hubTdbTree');\n" " treeDiv.jstree({\n" -" 'conditionalselect' : function (node, event) { return false; },\n" -" 'plugins' : ['conditionalselect', 'contextmenu']\n" +" 'conditionalselect' : function (node, event) { toggleExpansion(node, event); },\n" +" 'plugins' : ['conditionalselect', 'contextmenu'],\n" +" 'core' : { dblclick_toggle: false }\n" " });\n" " }\n\n" " return { init: init};\n\n" "}());\n" "\n" "$(function () {\n" " hubSearchTree.init();\n" "});\n" ); cartWebEnd(); } char *excludeVars[] = {"Submit", "submit", "hc_one_url", hgHubCheckUrl, hgHubDoClear, hgHubDoDisconnect,hgHubDoRedirect, hgHubDataText,