6f07cab7fdf96c16066566d551fc310d0d8afb52 max Tue Mar 1 13:36:13 2016 -0800 for patents track, refs #14486: - two additional trackDb statements to remove or separate extra fields of bigBed files in track hubs - changes to hgc to format extra fields as a table, looks somewhat nicer - two scripts to reformat patent tables to bigBed files diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c index 9325cf9..e95dc54 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -932,55 +932,50 @@ * return itemName. */ { char *sql = trackDbSetting(tdb, "idInUrlSql"); char *id = itemName; if (sql != NULL) { char query[1024]; sqlSafef(query, sizeof(query), sql, itemName); struct sqlConnection *conn = hAllocConn(database); id = sqlQuickString(conn, query); hFreeConn(&conn); } return id; } -char* constructUrl(struct trackDb *tdb, char *urlSetting, char *idInUrl, boolean encode) +char* getUrlSetting(struct trackDb *tdb, char* urlSetting) +/* get the "url" setting for the current track */ { -/* construct the url by replacing $$, etc in the url given by urlSetting. - * Replace $$ with itemName. */ - -// check the url setting prefix and get the correct url setting from trackDb char *url; if (sameWord(urlSetting, "url")) url = tdb->url; else url = trackDbSetting(tdb, urlSetting); - -if (url == NULL || url[0] == 0) - return NULL; - -char* eUrl = replaceInUrl(url, idInUrl, cart, database, seqName, winStart, winEnd, tdb->track, encode); -return eUrl; +return url; } void printIframe(struct trackDb *tdb, char *itemName) /* print an iframe with the URL specified in trackDb (iframeUrl), can have * the standard codes in it (like $$ for itemName, etc) */ { -char* eUrl = constructUrl(tdb, "iframeUrl", itemName, FALSE); +char *url = getUrlSetting(tdb, "iframeUrl"); +if (url==NULL) + return; +char *eUrl = replaceInUrl(url, itemName, cart, database, seqName, winStart, winEnd, tdb->track, FALSE); if (eUrl==NULL) return; char *iframeOptions = trackDbSettingOrDefault(tdb, "iframeOptions", "width='100%%' height='1024'"); // Resizing requires the hgcDetails pages to include a bit of javascript. // // Explanation how this works and why the javascript is needed: // http://stackoverflow.com/questions/153152/resizing-an-iframe-based-on-content // In short: // - iframes have a fixed size in html, resizing can only be done in javascript // - the iframed page cannot call the resize() function in the hgc html directly, as they have // been loaded from different webservers // - one way around it is that the iframed page includes a helper page on our server and // send their size to the helper page (pages can call functions of included pages) // - the helper page then sends the size back to hgc (pages on the same server can @@ -993,49 +988,64 @@ { \ document.getElementById('hgcIframe').height = parseInt(height)+10; \ } \ </script> \ \ <iframe id='hgcIframe' src='%s' %s></iframe> \ <p>", eUrl, iframeOptions); } void printCustomUrlWithLabel(struct trackDb *tdb, char *itemName, char *itemLabel, char *urlSetting, boolean encode) /* Print custom URL specified in trackDb settings. */ { char urlLabelSetting[32]; // replace the $$ and other wildchards with the url given in tdb -char* eUrl = constructUrl(tdb, urlSetting, itemName, encode); +char *url = getUrlSetting(tdb, "url"); +//char* eUrl = constructUrl(tdb, url, itemName, encode); +if (url==NULL) + return; + +char* eUrl = replaceInUrl(url, itemName, cart, database, seqName, winStart, winEnd, tdb->track, encode); if (eUrl==NULL) return; /* create the url label setting for trackDb from the url setting prefix */ safef(urlLabelSetting, sizeof(urlLabelSetting), "%sLabel", urlSetting); -printf("<B>%s </B>", - trackDbSettingOrDefault(tdb, urlLabelSetting, "Outside Link:")); +char *linkLabel = trackDbSettingOrDefault(tdb, urlLabelSetting, "Outside Link:"); + +// if we got no item name from hgTracks or the item name does not appear in the URL +// there is no need to show the item name at all +if (isEmpty(itemName) || !stringIn("$$", url)) + { + printf("<A TARGET=_blank HREF='%s'>%s</A><BR>",eUrl, linkLabel); + return; + } + +printf("<B>%s </B>",linkLabel); + printf("<A HREF=\"%s\" target=_blank>", eUrl); if (sameWord(tdb->table, "npredGene")) { printf("%s (%s)</A><BR>\n", itemName, "NCBI MapView"); } else { char *label = itemName; - if (isNotEmpty(itemLabel) && !sameString(itemName, itemLabel)) + if (isNotEmpty(itemLabel) && sameString(itemName, itemLabel)) label = itemLabel; printf("%s</A><BR>\n", label); } //freeMem(&eUrl); small memory leak } void printCustomUrl(struct trackDb *tdb, char *itemName, boolean encode) /* Wrapper to call printCustomUrlWithLabel using the url setting in trackDb */ { char urlSetting[10]; safef(urlSetting, sizeof(urlSetting), "url"); printCustomUrlWithLabel(tdb, itemName, itemName, urlSetting, encode); } @@ -1466,38 +1476,50 @@ } // split the id into parts and print each part as a link struct slName *slIds = slNameListFromComma(idList); struct slName *itemId = NULL; // handle id->name mapping for multi-source items int nameCount; char **idNames = getIdNameMap(tdb, col, &nameCount); printf("<td>"); for (itemId = slIds; itemId!=NULL; itemId = itemId->next) { if (itemId != slIds) printf(", "); - char *itemName = itemId->name; + char *itemName = trimSpaces(itemId->name); + if (idNames) { unsigned int id = sqlUnsigned(itemName); if (id < nameCount) itemName = idNames[sqlUnsigned(itemName)]; } - char *idUrl = replaceInUrl(url, trimSpaces(itemName), cart, database, seqName, winStart, + + // a | character can optionally be used to separate the ID used for $$ from the name shown in the link (like in Wikimedia markup) + char *idForUrl = itemName; + if (strstr(itemName, "|")) + { + char *parts[2]; + chopString(itemName, "|", parts, ArraySize(parts)); + idForUrl = parts[0]; + itemName = parts[1]; + } + + char *idUrl = replaceInUrl(url, idForUrl, cart, database, seqName, winStart, winEnd, tdb->track, TRUE); printf("<a href=\"%s\" target=\"_blank\">%s</a>", idUrl, itemName); } printf("</td></tr>\n"); freeMem(slIds); //freeMem(idNames); } int extraFieldsPrint(struct trackDb *tdb,struct sqlResult *sr,char **fields,int fieldCount) // Any extra bed or bigBed fields (defined in as and occurring after N in bed N + types. // sr may be null for bigBeds. // Returns number of extra fields actually printed. { struct sqlConnection *conn = NULL ; if (!trackHubDatabase(database)) @@ -1510,66 +1532,102 @@ // We are trying to print extra fields so we need to figure out how many fields to skip int start = 0; char *type = cloneString(tdb->type); char *word = nextWord(&type); if (word && (sameWord(word,"bed") || sameWord(word,"bigBed") || sameWord(word,"bigGenePred"))) { if (NULL != (word = nextWord(&type))) start = sqlUnsigned(word); else // custom beds and bigBeds may not have full type "begBed 9 +" start = max(0,slCount(as->columnList) - fieldCount); } int count = 0; struct asColumn *col = as->columnList; char *urlsStr = trackDbSetting(tdb, "urls"); struct hash* fieldToUrl = hashFromString(urlsStr); +boolean skipEmptyFields = trackDbSettingOn(tdb, "skipEmptyFields"); +// make list of fields to skip +char *skipFieldsStr = trackDbSetting(tdb, "skipFields"); +struct slName *skipIds = NULL; +if (skipFieldsStr) + skipIds = slNameListFromComma(skipFieldsStr); + +// make list of fields that are separated from other fields +char *sepFieldsStr = trackDbSetting(tdb, "sepFields"); +struct slName *sepFields = NULL; +if (sepFieldsStr) + sepFields = slNameListFromComma(sepFieldsStr); + +// iterate over fields, print as table rows for (;col != NULL && count < fieldCount;col=col->next) { if (start > 0) // skip past already known fields { start--; continue; } int ix = count; if (sr != NULL) { ix = sqlFieldColumn(sr, col->name); // If sr provided, name must match sql columnn name! if (ix == -1 || ix > fieldCount) // so extraField really just provides a label continue; } - // Print as table rows + char *fieldName = col->name; + if (count == 0) - printf("<br><table>"); + printf("<br><table class='bedExtraTbl'>"); + count++; - printf("<tr><td><B>%s:</B></td>", col->comment); + + // do not print a row if the fieldName from the .as file is in the "skipFields" list + if (skipIds && slNameInList(skipIds, fieldName)) + continue; + + // split this table to separate current row from the previous one, if the trackDb option is set + if (sepFields && slNameInList(sepFields, fieldName)) + printf("</tr></table>\n<p>\n<table class='bedExtraTbl'>"); + + // skip this row if it's empty and "skipEmptyFields" option is set + if (skipEmptyFields && isEmpty(fields[ix])) + continue; + + // field description + printf("<tr><td>%s</td>", col->comment); // bold style now in HGStyle.css + if (col->isList || col->isArray || col->lowType->stringy || asTypesIsInt(col->lowType->type)) printIdOrLinks(col, fieldToUrl, tdb, fields[ix]); else if (asTypesIsFloating(col->lowType->type)) { double valDouble = strtod(fields[ix],NULL); if (errno == 0 && valDouble != 0) printf("<td>%g</td></tr>\n", valDouble); else printf("<td>%s</td></tr>\n", fields[ix]); // decided not to print error } else printf("<td>%s</td></tr>\n", fields[ix]); } asObjectFree(&as); freeMem(fieldToUrl); +if (skipIds) + slFreeList(skipIds); +if (sepFields) + slFreeList(sepFields); + if (count > 0) printf("</table>\n"); return count; } void genericBedClick(struct sqlConnection *conn, struct trackDb *tdb, char *item, int start, int bedSize) /* Handle click in generic BED track. */ { char table[64]; boolean hasBin; struct bed *bed; char query[512]; struct sqlResult *sr; @@ -3881,31 +3939,31 @@ if (sameString(type, "maf") || sameString(type, "wigMaf") || sameString(type, "bigMaf") || sameString(type, "netAlign") || sameString(type, "encodePeak")) headerItem = NULL; else if (( sameString(type, "narrowPeak") || sameString(type, "broadPeak") || sameString(type, "gappedPeak") ) && headerItem && sameString(headerItem, ".") ) headerItem = NULL; } /* Print header. */ genericHeader(tdb, headerItem); itemForUrl = getIdInUrl(tdb, item); -if (itemForUrl != NULL && itemForUrl[0] != 0) +if (itemForUrl != NULL && trackDbSetting(tdb, "url")) { printCustomUrl(tdb, itemForUrl, item == itemForUrl); printIframe(tdb, itemForUrl); } if (plus != NULL) { fputs(plus, stdout); } if (container != NULL) { genericContainerClick(conn, container, tdb, item, itemForUrl); } else if (wordCount > 0)