87dbdc612e3d8aeb3a7c564dbdcea1adc77b7e67 jnavarr5 Tue Apr 29 14:40:44 2025 -0700 Staging the Table Browser tutorial. Adding <DIV> sections to the main table browser page for the tutorial. refs #35126 diff --git src/hg/hgTables/mainPage.c src/hg/hgTables/mainPage.c index 0fa0f9cddda..4ea5fd10bc8 100644 --- src/hg/hgTables/mainPage.c +++ src/hg/hgTables/mainPage.c @@ -446,88 +446,101 @@ jsInlineF("function checkForCsv(event) {\n" "var outputType = document.getElementById('outputTypeDropdown').value;\n" "if (outputType === 'primaryTable' || outputType === 'selectedFields') {\n" " document.getElementById('%s').parentElement.style.display='';\n" " document.getElementById('excelOutNote').style.display='';\n" "} else {\n" " document.getElementById('%s').parentElement.style.display='none';\n" " document.getElementById('excelOutNote').style.display='none';\n" "}\n" "}\n" "$(document).ready(checkForCsv);\n" , hgtaOutSep, hgtaOutSep); jsAddEventForId("change", "outputTypeDropdown", "checkForCsv"); +/* + * Code to add in the interactive tutorial*/ +if (cfgOptionBooleanDefault("showTutorial", TRUE)) + { + puts("<script src=\"https://cdn.jsdelivr.net/npm/shepherd.js@11.0.1/dist/js/shepherd.min.js\"></script>"); + puts("<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/shepherd.js@11.0.1/dist/css/shepherd.css\"/>"); + jsIncludeFile("tableBrowserTutorial.js",NULL); + if (sameOk(cgiOptionalString("startTutorial"), "true")) + { + jsInline("tableBrowserTour.start();"); + } + } + if (!cfgOptionBooleanDefault("hgta.disableSendOutput", FALSE)) { hPrintf(" Send output to "); struct dyString *dy = dyStringNew(256); dyStringAppend(dy, "document.getElementById('checkboxGreat').checked=false;"); if (isGenomeSpaceEnabled()) dyStringAppend(dy, "document.getElementById('checkboxGenomeSpace').checked=false;"); dyStringAppend(dy, "return true;"); cgiMakeCheckBoxWithId("sendToGalaxy", doGalaxy(), "checkboxGalaxy"); jsOnEventById("click", "checkboxGalaxy", dy->string); hPrintf("<A HREF=\""GALAXY_URL_BASE"\" target=_BLANK>Galaxy</A>\n"); nbSpaces(2); cgiMakeCheckBoxWithId("sendToGreat", doGreat(), "checkboxGreat"); jsOnEventById("click", "checkboxGreat", "return onSelectGreat();"); hPrintf(" <A HREF=\"http://great.stanford.edu\" target=_BLANK>GREAT</A>"); if (isGenomeSpaceEnabled()) { nbSpaces(2); cgiMakeCheckBoxWithId("sendToGenomeSpace", doGenomeSpace(), "checkboxGenomeSpace"); jsOnEventById("click", "checkboxGenomeSpace", "document.getElementById('checkboxGreat').checked=false;" "document.getElementById('checkboxGalaxy').checked=false; return true;"); hPrintf(" <A HREF=\"http://www.genomespace.org\" target=_BLANK>GenomeSpace</A>"); } } -hPrintf("</TD></TR>\n"); +hPrintf("</DIV></TD></TR>\n"); } struct outputType otAllFields = { NULL, outPrimaryTable,"All fields from selected table", }; struct outputType otSelected = { NULL, outSelectedFields, "Selected fields from primary and related tables", }; struct outputType otSequence = { NULL, outSequence, "Sequence", }; struct outputType otPal = { NULL, outPalOptions, "CDS FASTA alignment from multiple alignment", }; struct outputType otGff = { NULL, outGff, "GTF - gene transfer format (limited)", }; struct outputType otBed = { NULL, outBed, "BED - browser extensible data", }; struct outputType otCustomTrack = { NULL, outCustomTrack, "Custom track", }; struct outputType otHyperlinks = { NULL, outHyperlinks, "Hyperlinks to Genome Browser", }; struct outputType otWigData = { NULL, outWigData, "Data points", }; struct outputType otWigBed = { NULL, outWigBed, "Bed format", }; struct outputType otMaf = { NULL, outMaf, "MAF - multiple alignment format", }; struct outputType otChromGraphData = { NULL, outChromGraphData, "Data points", }; struct outputType otMicroarrayNames = { NULL, outMicroarrayNames, "Microarray names", }; struct outputType otMicroarrayGroupings = { NULL, outMicroarrayGroupings, "Microarray groupings", }; static void showOutputTypeRow(boolean isWig, boolean isBedGr, boolean isPositional, boolean isMaf, boolean isChromGraphCt, boolean isPal, boolean isMicroarray, boolean isHalSnake) /* Print output line. */ { struct outputType *otList = NULL, *otDefault = NULL; boolean bedifiedOnly = (anySubtrackMerge(database, curTable) || anyIntersection()); -hPrintf("<TR><TD><B>Output format:</B>\n"); +hPrintf("<TR><TD><DIV ID=\"output-select\"><B>Output format:</B>\n"); if (isBedGr) { if (! bedifiedOnly) { slAddTail(&otList, &otAllFields); slAddTail(&otList, &otSelected); } slAddTail(&otList, &otWigData); slAddTail(&otList, &otWigBed); slAddTail(&otList, &otCustomTrack); slAddTail(&otList, &otHyperlinks); } else if (isWig) { @@ -662,89 +675,89 @@ isChromGraphCt = FALSE, isPal = FALSE, isArray = FALSE, isBam = FALSE, isVcf = FALSE, isHalSnake = FALSE, isLongTabix = FALSE, isHic = FALSE; boolean gotClade = hGotClade(); struct hTableInfo *hti = NULL; hPrintf("<TABLE BORDER=0>\n"); int stepNumber = 1; printStep(stepNumber++); /* Print clade, genome and assembly line. */ { if (gotClade) { - hPrintf("<TR><TD><B>Clade:</B>\n"); + hPrintf("<TR><TD><DIV ID=\"genome-select\"><B>Clade:</B>\n"); printCladeListHtml(hGenome(database), "change", onChangeClade()); nbSpaces(3); hPrintf("<B>Genome:</B>\n"); printGenomeListForCladeHtml(database, "change", onChangeOrg()); } else { - hPrintf("<TR><TD><B>Genome:</B>\n"); + hPrintf("<TR><TD><DIV ID=\"genome-select\"><B>Genome:</B>\n"); printGenomeListHtml(database, "change", onChangeOrg()); } nbSpaces(3); hPrintf("<B>Assembly:</B>\n"); printAssemblyListHtml(database, "change", onChangeDb()); - hPrintf("</TD></TR>\n"); + hPrintf("</DIV></TD></TR>\n"); } /* Print group and track line. */ { - hPrintf("<TR><TD>"); + hPrintf("<TR><TD><DIV ID=\"track-select\">"); selGroup = showGroupField(hgtaGroup, "change", onChangeGroupOrTrack(), conn, hAllowAllTables()); nbSpaces(3); curTrack = showTrackField(selGroup, hgtaTrack, "change", onChangeGroupOrTrack(), FALSE); nbSpaces(3); - hPrintf("</TD></TR>\n"); + hPrintf("</DIV></TD></TR>\n"); } /* Print table line. */ { - hPrintf("<TR><TD>"); + hPrintf("<TR><TD><DIV ID=\"table-select\">"); curTable = showTableField(curTrack, hgtaTable, TRUE); if (isHubTrack(curTable) || hashFindVal(fullTableToTdbHash, curTable) != NULL) /* In same database */ { hti = getHti(database, curTable, conn); isPositional = htiIsPositional(hti); } isLongTabix = isLongTabixTable( curTable); isBam = isBamTable(curTable); isHic = isHicTable(curTable); isVcf = isVcfTable(curTable, NULL); isWig = isWiggle(database, curTable); if (isBigWigTable(curTable)) { isPositional = TRUE; isWig = TRUE; } isHalSnake = isHalTable( curTable); isMaf = isMafTable(database, curTrack, curTable); isBedGr = isBedGraph(curTable); isArray = isMicroarray(curTrack, curTable); struct trackDb *tdb = findTdbForTable(database, curTrack, curTable, ctLookupName); isPal = isPalCompatible(conn, tdb, curTable); nbSpaces(1); if (isCustomTrack(curTable)) { isChromGraphCt = isChromGraph(tdb); } cgiMakeButton(hgtaDoSchema, "Data format description"); - hPrintf("</TD></TR>\n"); + hPrintf("</DIV></TD></TR>\n"); } if (curTrack == NULL) { struct trackDb *tdb = hTrackDbForTrack(database, curTable); struct trackDb *cTdb = hCompositeTrackDbForSubtrack(database, tdb); if (cTdb) curTrack = cTdb; else curTrack = tdb; isMaf = isMafTable(database, curTrack, curTable); } /* Table-specific options */ if (isHicTable(curTable)) @@ -763,31 +776,31 @@ char *regionType; if (cartVarExists(cart, "hgFind.matches")) // coming back from a search regionType = cartUsualString(cart, hgtaRegionType, hgtaRegionTypeRange); else regionType = cartUsualString(cart, hgtaRegionType, hgtaRegionTypeGenome); char *range = cartUsualString(cart, hgtaRange, ""); if (isPositional) { boolean doEncode = FALSE; if (!trackHubDatabase(database)) doEncode = sqlTableExists(conn, "encodeRegions"); - hPrintf("<TR><TD><B>Region:</B>\n"); + hPrintf("<TR><TD><DIV ID=\"position-controls\"><B>Region:</B>\n"); /* If regionType not allowed force it to "genome". */ if ((sameString(regionType, hgtaRegionTypeUserRegions) && userRegionsFileName() == NULL) || (sameString(regionType, hgtaRegionTypeEncode) && !doEncode)) regionType = hgtaRegionTypeGenome; // Is "genome" is not allowed because of tdb 'tableBrowser noGenome'? boolean disableGenome = ((curTrack && cartTrackDbIsNoGenome(database, curTrack->table)) || (curTable && cartTrackDbIsNoGenome(database, curTable))); // If "genome" is selected but not allowed, force it to "range": if (sameString(regionType, hgtaRegionTypeGenome) && disableGenome) regionType = hgtaRegionTypeRange; jsTrackingVar("regionType", regionType); if (disableGenome) { @@ -811,60 +824,61 @@ hgtaRange, hgtaRange, range); jsOnEventById("focus", hgtaRange, jsRadioUpdate(hgtaRegionType, "regionType", "range")); cgiMakeButton(hgtaDoLookupPosition, "Lookup"); hPrintf(" "); if (userRegionsFileName() != NULL) { makeRegionButton(hgtaRegionTypeUserRegions, regionType); hPrintf(" Defined regions "); cgiMakeButton(hgtaDoSetUserRegions, "Change"); hPrintf(" "); cgiMakeButton(hgtaDoClearUserRegions, "Clear"); } else cgiMakeButton(hgtaDoSetUserRegions, "Define regions"); + hPrintf("</DIV>"); hPrintf("</TD></TR>\n"); if (disableGenome) { // no need to check curTrack for NULL, disableGenome can only be set if curTable is set hPrintf("<tr><td>"); printNoGenomeWarning(curTrack); hPrintf("</td></tr>"); } } else { /* Need to put at least stubs of cgi variables in for JavaScript to work. */ jsTrackingVar("regionType", regionType); cgiMakeHiddenVar(hgtaRange, range); cgiMakeHiddenVar(hgtaRegionType, regionType); } /* Select identifiers line (if applicable). */ if (!isWig && getIdField(database, curTrack, curTable, hti) != NULL) { - hPrintf("<TR><TD><B>Identifiers (names/accessions):</B>\n"); + hPrintf("<TR><TD><DIV ID=\"identifiers-controls\"><B>Identifiers (names/accessions):</B>\n"); cgiMakeButton(hgtaDoPasteIdentifiers, "Paste list"); hPrintf(" "); cgiMakeButton(hgtaDoUploadIdentifiers, "Upload list"); if (identifierFileName() != NULL) { hPrintf(" "); cgiMakeButton(hgtaDoClearIdentifiers, "Clear list"); } - hPrintf("</TD></TR>\n"); + hPrintf("</DIV></TD></TR>\n"); } } /* button for option page here (median/log-ratio, etc) */ printStep(stepNumber++); /* Filter line. */ { hPrintf("<TR><TD><B>Filter:</B>\n"); if (anyFilter()) { cgiMakeButton(hgtaDoFilterPage, "Edit"); hPrintf(" "); cgiMakeButton(hgtaDoClearFilter, "Clear"); @@ -963,61 +977,61 @@ hPrintf("</TD></TR>\n"); } /* Print output type line. */ printStep(stepNumber++); showOutputTypeRow(isWig, isBedGr, isPositional, isMaf, isChromGraphCt, isPal, isArray, isHalSnake); /* Print output destination line. */ { char *compressType = cartUsualString(cart, hgtaCompressType, textOutCompressNone); char *fieldSep = cartUsualString(cart, hgtaOutSep, outTab); char *fileName = cartUsualString(cart, hgtaOutFileName, ""); hPrintf("<TR><TD>\n"); - hPrintf("<B>Output filename:</B> "); + hPrintf("<DIV ID=\"filename-select\"><B>Output filename:</B> "); cgiMakeTextVar(hgtaOutFileName, fileName, 29); - hPrintf(" (<span id='excelOutNote' style='display:none'>add .csv extension if opening in Excel, </span>leave blank to keep output in browser)</TD></TR>\n"); + hPrintf(" (<span id='excelOutNote' style='display:none'>add .csv extension if opening in Excel, </span>leave blank to keep output in browser)</DIV></TD></TR>\n"); hPrintf("<TR><TD>\n"); hPrintf("<B>Output field separator: </B>"); // tab or csv output cgiMakeRadioButton(hgtaOutSep, outTab, sameWord(outTab, fieldSep)); hPrintf(" tsv (tab-separated)  "); cgiMakeRadioButton(hgtaOutSep, outCsv, sameWord(outCsv, fieldSep)); hPrintf(" csv (for excel) "); hPrintf("</TD></TR>\n"); hPrintf("<TR><TD>\n"); hPrintf("<B>File type returned: </B>"); cgiMakeRadioButton(hgtaCompressType, textOutCompressNone, sameWord(textOutCompressNone, compressType)); hPrintf(" Plain text "); cgiMakeRadioButton(hgtaCompressType, textOutCompressGzip, sameWord(textOutCompressGzip, compressType)); hPrintf(" Gzip compressed"); hPrintf("</TD></TR>\n"); } hPrintf("</TABLE>\n"); /* Submit buttons. */ { - hPrintf("<BR>\n"); + hPrintf("<BR><DIV ID=\"submit-select\">\n"); if (isWig || isBam || isVcf || isLongTabix || isHic) { char *name; extern char *maxOutMenu[]; char *maxOutput = maxOutMenu[0]; if (isCustomTrack(curTable)) name=filterFieldVarName("ct", curTable, "_", filterMaxOutputVar); else name=filterFieldVarName(database,curTable, "_",filterMaxOutputVar); maxOutput = cartUsualString(cart, name, maxOutMenu[0]); if (isWig) hPrintf( @@ -1033,30 +1047,31 @@ "</I><BR>", maxOutput); } else if (anySubtrackMerge(database, curTable) || anyIntersection()) { hPrintf("<I>Note: The all fields and selected fields output formats " "are not available when a%s has been specified.</I><BR>", canSubtrackMerge ? " subtrack merge or intersection" : "n intersection"); } cgiMakeButton(hgtaDoTopSubmit, "Get output"); hPrintf(" "); if (isPositional || isWig) { cgiMakeButton(hgtaDoSummaryStats, "Summary/statistics"); hPrintf(" "); } + hPrintf("</DIV>"); #ifdef SOMETIMES hPrintf(" "); cgiMakeButton(hgtaDoTest, "test"); #endif /* SOMETIMES */ } hPrintf("<P></P>"); } static char *getGenomeSpaceText() /* fetch GenomeSpace text if enabled */ { if (isGenomeSpaceEnabled()) { return