f69a8b38592faaedf9c6f254ce5d56e73d91ac64
jnavarr5
  Tue Sep 30 10:48:18 2025 -0700
Initial commit of the customTrack tutorial, refs #34354

diff --git src/hg/hgCustom/hgCustom.c src/hg/hgCustom/hgCustom.c
index 9d471fb5713..0781097448b 100644
--- src/hg/hgCustom/hgCustom.c
+++ src/hg/hgCustom/hgCustom.c
@@ -13,30 +13,31 @@
 #include "hdb.h"
 #include "hui.h"
 #include "hCommon.h"
 #include "customTrack.h"
 #include "customFactory.h"
 #include "portable.h"
 #include "errCatch.h"
 #include "knetUdc.h"
 #include "udc.h"
 #include "net.h"
 #include "jsHelper.h"
 #include <signal.h>
 #include "trackHub.h"
 #include "botDelay.h"
 #include "chromAlias.h"
+#include "hgConfig.h"
 
 static long loadTime = 0;
 static boolean issueBotWarning = FALSE;
 #define delayFraction   0.25	/* same as hgTracks */
 
 void usage()
 /* Explain usage and exit. */
 {
 errAbort(
   "hgCustom - Custom track management CGI\n"
   "usage:\n"
   "   hgCustom <CGI settings>\n"
   );
 }
 
@@ -163,30 +164,43 @@
 boolean gotClade = FALSE;
 boolean isUpdateForm = FALSE;
 if (ct)
     {
     isUpdateForm = TRUE;
     dataUrl = ctDataUrl(ct);
     }
 else
     /* add form needs clade for assembly menu */
     gotClade = hGotClade();
 
 jsIncludeFile("jquery.js", NULL);
 jsIncludeFile("hgCustom.js", NULL);
 jsIncludeFile("utils.js", NULL);
 jsIncludeFile("ajax.js", NULL);
+if (cfgOptionBooleanDefault("showTutorial", TRUE))
+    {
+    jsIncludeFile("shepherd.min.js", NULL);
+    webIncludeResourceFile("shepherd.css");
+    jsIncludeFile("jquery-ui.js", NULL);
+    webIncludeResourceFile("jquery-ui.css");
+    //jsIncludeFile("tutorialPopup.js", NULL);
+    jsIncludeFile("customTrackTutorial.js", NULL);
+    if (sameOk(cgiOptionalString("startCustomTutorial"), "true"))
+        {
+        jsInline("var startCustomTutorialOnLoad = true;");
+        }
+    }
 
 /* main form */
 printf("<FORM ACTION=\"%s\" METHOD=\"%s\" "
     " ENCTYPE=\"multipart/form-data\" NAME=\"mainForm\" id='mainForm'>\n",
     hgCustomName(), cartUsualString(cart, "formMethod", "POST"));
 jsOnEventById("submit", "mainForm", "$('input[name=Submit]').attr('disabled', 'disabled');");
 cartSaveSession(cart);
 
 if (!isUpdateForm)
     {
     /* Print clade, genome and assembly  */
     /* NOTE: this uses an additional, hidden form (orgForm), below */
     char *onChangeDb = "document.orgForm.db.value = document.mainForm.db.options[document.mainForm.db.selectedIndex].value; document.orgForm.submit();";
     char *onChangeOrg = "document.orgForm.org.value = document.mainForm.org.options[document.mainForm.org.selectedIndex].value; document.orgForm.db.value = 0; document.orgForm.submit();";
     char *onChangeClade = "document.orgForm.clade.value = document.mainForm.clade.options[document.mainForm.clade.selectedIndex].value; document.orgForm.org.value = 0; document.orgForm.db.value = 0; document.orgForm.submit();";