e0db353cfefb9bde9cce31d6a2c2d2762dc1de4a kate Wed Sep 12 17:19:14 2018 -0700 IMplement fieldName> expansion in trackDb url setting. refs #22078 diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c index 1307b9e..42c61c1 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -885,73 +885,76 @@ if (sameWord(urlSetting, "url")) url = tdb->url; else url = trackDbSetting(tdb, urlSetting); 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 *url = getUrlSetting(tdb, "iframeUrl"); if (url==NULL) return; -char *eUrl = replaceInUrl(url, itemName, cart, database, seqName, winStart, winEnd, tdb->track, FALSE); +char *eUrl = replaceInUrl(url, itemName, cart, database, seqName, winStart, winEnd, + tdb->track, FALSE, NULL); 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 // call each others' functions) // width='%s' height='%s' src='%s' seamless scrolling='%s' frameborder='%s' printf(" \ <script> \ function resizeIframe(height) \ { \ 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) +void printCustomUrlWithLabel(struct trackDb *tdb, char *itemName, char *itemLabel, + char *urlSetting, boolean encode, struct slPair *fields) /* Print custom URL specified in trackDb settings. */ { char urlLabelSetting[32]; // replace the $$ and other wildchards with the url given in tdb char *url = getUrlSetting(tdb, urlSetting); //char* eUrl = constructUrl(tdb, url, itemName, encode); if (url==NULL || isEmpty(url)) return; -char* eUrl = replaceInUrl(url, itemName, cart, database, seqName, winStart, winEnd, tdb->track, encode); +char *eUrl = replaceInUrl(url, itemName, cart, database, seqName, winStart, winEnd, tdb->track, + encode, fields); if (eUrl==NULL) return; /* create the url label setting for trackDb from the url setting prefix */ safef(urlLabelSetting, sizeof(urlLabelSetting), "%sLabel", urlSetting); 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; } @@ -962,44 +965,58 @@ if (sameWord(tdb->table, "npredGene")) { printf("%s (%s)</A><BR>\n", itemName, "NCBI MapView"); } else { char *label = itemName; 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 */ +void printCustomUrlWithFields(struct trackDb *tdb, char *itemName, char *itemLabel, boolean encode, struct slPair *fields) +/* Wrapper to call printCustomUrlWithLabel with additional fields to substitute */ { char urlSetting[10]; safef(urlSetting, sizeof(urlSetting), "url"); -printCustomUrlWithLabel(tdb, itemName, itemName, urlSetting, encode); +printCustomUrlWithLabel(tdb, itemName, itemName, urlSetting, encode, fields); +} + +void printCustomUrl(struct trackDb *tdb, char *itemName, boolean encode) +/* Wrapper to call printCustomUrlWithLabel using the url setting in trackDb */ +{ +printCustomUrlWithFields(tdb, itemName, itemName, encode, NULL); +} + +void printOtherCustomUrlWithFields(struct trackDb *tdb, char *itemName, char *urlSetting, + boolean encode, struct slPair *fields) +/* Wrapper to call printCustomUrlWithLabel to use another url setting other than url in trackDb e.g. url2, this allows the use of multiple urls for a track + to be set in trackDb. */ +{ +printCustomUrlWithLabel(tdb, itemName, itemName, urlSetting, encode, fields); } void printOtherCustomUrl(struct trackDb *tdb, char *itemName, char* urlSetting, boolean encode) /* Wrapper to call printCustomUrlWithLabel to use another url setting other than url in trackDb e.g. url2, this allows the use of multiple urls for a track to be set in trackDb. */ { -printCustomUrlWithLabel(tdb, itemName, itemName, urlSetting, encode); +printCustomUrlWithLabel(tdb, itemName, itemName, urlSetting, encode, NULL); } void genericSampleClick(struct sqlConnection *conn, struct trackDb *tdb, char *item, int start, int smpSize) /* Handle click in generic sample (wiggle) track. */ { char table[64]; boolean hasBin; struct sample *smp; char query[512]; struct sqlResult *sr; char **row; boolean firstTime = TRUE; hFindSplitTable(database, seqName, tdb->table, table, &hasBin); @@ -1432,31 +1449,31 @@ } // 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; boolean encode = TRUE; if (strstr(itemName, "|")) { char *parts[2]; chopString(itemName, "|", parts, ArraySize(parts)); idForUrl = parts[0]; itemName = parts[1]; encode = FALSE; // assume the link is already encoded } char *idUrl = replaceInUrl(url, idForUrl, cart, database, seqName, winStart, - winEnd, tdb->track, encode); + winEnd, tdb->track, encode, NULL); printf("<a href=\"%s\" target=\"_blank\">%s</a>", idUrl, itemName); } printf("</td></tr>\n"); freeMem(slIds); //freeMem(idNames); } int extraFieldsStart(struct trackDb *tdb, int fieldCount, struct asObject *as) /* return the index of the first extra field */ { int start = 0; char *type = cloneString(tdb->type); char *word = nextWord(&type); if (word && (sameWord(word,"bed") || sameWord(word,"bigBed") || sameWord(word,"bigGenePred") || sameWord(word,"bigPsl") || sameWord(word,"bigBarChart"))) { @@ -1488,30 +1505,56 @@ { struct slPair *slp; AllocVar(slp); char *fieldName = col->name; char *fieldVal = fields[count]; slp->name = fieldName; slp->val = fieldVal; slAddHead(&extraFields, slp); count++; //printf("name %s, val %s, idx %d<br>", fieldName, fieldVal, count); } slReverse(extraFields); return extraFields; } +struct slPair *getFields(struct trackDb *tdb, char **row) +/* return field names and their values as a list of slPairs. */ +// TODO: refactor with getExtraFields +{ +struct asObject *as = asForDb(tdb, database); +if (as == NULL) + return NULL; +int fieldCount = slCount(as->columnList); +struct slPair *fields = NULL; +struct asColumn *col = as->columnList; +int count = 0; +for (count = 0; col != NULL && count < fieldCount; col = col->next) + { + struct slPair *field; + AllocVar(field); + char *fieldName = col->name; + char *fieldVal = row[count]; + field->name = fieldName; + field->val = fieldVal; + slAddHead(&fields, field); + count++; + } +slReverse(fields); +return fields; +} + 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 asObject *as = asForDb(tdb, database); if (as == NULL) return 0; // We are trying to print extra fields so we need to figure out how many fields to skip int start = extraFieldsStart(tdb, fieldCount, as); struct asColumn *col = as->columnList; char *urlsStr = trackDbSettingClosestToHomeOrDefault(tdb, "urls", NULL); struct hash* fieldToUrl = hashFromString(urlsStr); @@ -4064,42 +4107,44 @@ type = words[0]; 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); +if (differentString(type, "bigInteract") && differentString(type, "interact")) + { + // skip generic URL code as these may have multiple items returned for a click itemForUrl = getIdInUrl(tdb, item); 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) { type = words[0]; if (sameString(type, "bed")) { int num = 0; if (wordCount > 1) num = atoi(words[1]); if (num < 3) num = 3; genericBedClick(conn, tdb, item, start, num); } @@ -4118,32 +4163,31 @@ } else if (sameString(type, "sample")) { int num = 9; genericSampleClick(conn, tdb, item, start, num); } else if (sameString(type, "genePred")) { char *pepTable = NULL, *mrnaTable = NULL; if ((wordCount > 1) && !sameString(words[1], ".")) pepTable = words[1]; if ((wordCount > 2) && !sameString(words[2], ".")) mrnaTable = words[2]; genericGenePredClick(conn, tdb, item, start, pepTable, mrnaTable); } - else if ( sameString(type, "bigPsl")) - { + else if ( sameString(type, "bigPsl")) { genericBigPslClick(conn, tdb, item, start, end); } else if (sameString(type, "psl")) { char *subType = "."; if (wordCount > 1) subType = words[1]; genericPslClick(conn, tdb, item, start, subType); } else if (sameString(type, "netAlign")) { if (wordCount < 3) errAbort("Missing field in netAlign track type field"); genericNetClick(conn, tdb, item, start, words[1], words[2]); } @@ -11957,31 +12001,31 @@ { if (!dbToLabel) errAbort("can not find trackDb dbPrefixLabels to correspond with dbPrefixUrls\n"); char *databasePrefix = cloneString(database); while (strlen(databasePrefix) && isdigit(lastChar(databasePrefix))) trimLastChar(databasePrefix); struct hashEl *hel = hashLookup(dbToUrl, databasePrefix); if (hel) { struct hashEl *label = hashLookup(dbToLabel, databasePrefix); if (!label) errAbort("missing trackDb dbPrefixLabels for database prefix: '%s'\n", databasePrefix); char *url = (char *)hel->val; char *labelStr = (char *)label->val; char *idUrl = replaceInUrl(url, nrl->externalId, cart, database, - nrl->externalId, winStart, winEnd, tdb->track, TRUE); + nrl->externalId, winStart, winEnd, tdb->track, TRUE, NULL); printf("<b>%s:</b> ", labelStr); printf("<a href='%s' target='_blank'>%s</a><br>\n", idUrl, nrl->externalId); } } } } if (differentWord(nrl->locusLinkId, "")) { printf("<b>Entrez Gene:</b> "); printf("<a href='https://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=Retrieve&dopt=Graphics&list_uids=%s' TARGET=_blank>", nrl->locusLinkId); printf("%s</a><br>\n", nrl->locusLinkId); } @@ -24980,31 +25024,31 @@ bed = bedLoadN(row+hasBin, 12); int lastBlk = bed->blockCount - 1; int endForUrl = (bed->chromStart + bed->chromStarts[lastBlk] + bed->blockSizes[lastBlk]); char *endFudge = trackDbSetting(tdb, "endFudge"); if (endFudge && !strstr(bed->name, "OEA")) endForUrl += atoi(endFudge); char sampleName[16]; safecpy(sampleName, sizeof(sampleName), tdb->table + strlen(KIDD_EICHLER_DISC_PREFIX)); touppers(sampleName); char itemPlus[2048]; safef(itemPlus, sizeof(itemPlus), "%s&o=%d&t=%d&g=%s_discordant&%s_discordant=full", cgiEncode(item), start, endForUrl, sampleName, sampleName); - printCustomUrlWithLabel(tdb, itemPlus, item, "url", FALSE); + printCustomUrlWithLabel(tdb, itemPlus, item, "url", FALSE, NULL); printKiddEichlerNcbiLinks(tdb, bed->name); printf("<B>Score:</B> %d<BR>\n", bed->score); printPosOnChrom(bed->chrom, bed->chromStart, bed->chromEnd, bed->strand, TRUE, bed->name); } sqlFreeResult(&sr); printTrackHtml(tdb); } void doBedDetail(struct trackDb *tdb, struct customTrack *ct, char *itemName) /* generate the detail page for a custom track of bedDetail type */ { char *table; struct bedDetail *r = NULL; struct sqlConnection *conn;