148452cbb04d1585ca0efb73cff479ccba0ea9d1
jnavarr5
Wed Nov 26 16:46:58 2025 -0800
Making edits based on Lou's feedback, refs #34354
diff --git src/hg/js/tutorials/customTrackTutorial.js src/hg/js/tutorials/customTrackTutorial.js
index 13610bd995b..140b97cdfdc 100644
--- src/hg/js/tutorials/customTrackTutorial.js
+++ src/hg/js/tutorials/customTrackTutorial.js
@@ -1,427 +1,427 @@
/* jshint esnext: true */
/* global Shepherd */
//Creating an IIFE to prevent global variable conflicts
(function() {
const customTrackTour = new Shepherd.Tour({
defaultStepOptions: {
cancelIcon: { enabled: true },
classes: 'class-1 class-2',
scrollTo: { behavior: 'smooth', block: 'center' }
},
useModalOverlay: true,
canClickTarget: false
});
// log when a tutorial is started (commented out for now)
customTrackTour.on('start', function() {
writeToApacheLog("customTrackTutorial start " + getHgsid());
});
var tutorialButtons = {
'back': {
action() {
return this.back();
},
classes: 'shepherd-button-secondary',
text: 'Back'
},
'next': {
action() {
return this.next();
},
text: 'Next'
},
'quit': {
action() {
return this.complete();
},
classes: 'shepherd-button-secondary',
text: 'Exit'
},
'load_bigWig': {
text: 'Load a bigWig example',
action () {
// Add text to the textarea
const textarea = document.querySelector('textarea[name="hgct_customText"]');
if (textarea.value.trim() === '') {
textarea.value = 'browser position chr21:33031596-33041570\n';
}
textarea.value += 'track type=bigWig name="bigWig variableStep" '+
'description="bigWig variableStep format" visibility=full '+
'autoScale=off viewLimits=5.0:25.0 color=255,200,0 '+
'yLineMark=11.76 yLineOnOff=on '+
'bigDataUrl="http://genome-test.gi.ucsc.edu/~hiram/ctDb/wigVariableStep.bw"\n';
// Optional: trigger any change events if the page listens for them
textarea.dispatchEvent(new Event('change', { bubbles: true }));
textarea.dispatchEvent(new Event('input', { bubbles: true }));
}
},
'load_bigBed': {
text: 'Load a bigBed example',
action () {
// Add text to the textarea
const textarea = document.querySelector('textarea[name="hgct_customText"]');
if (textarea.value.trim() === '') {
textarea.value = 'browser position chr21:33031596-33041570\n';
}
textarea.value += 'track type=bigBed db="hg19" name="bigBed12" type="bigBed 12" '+
'bigDataUrl="http://genome-test.gi.ucsc.edu/~hiram/ctDb/bigBedType12.bb "'+
'visibility=pack itemRgb="On"\n';
// Optional: trigger any change events if the page listens for them
textarea.dispatchEvent(new Event('change', { bubbles: true }));
textarea.dispatchEvent(new Event('input', { bubbles: true }));
}
},
'load_bed': {
text: 'Load a BED example',
action () {
// Add text to the textarea
const textarea = document.querySelector('textarea[name="hgct_customText"]');
if (textarea.value.trim() === '') {
textarea.value = 'browser position chr21:33031596-33041570\n';
}
textarea.value += 'track name="BED 6 example" priority="40" visibility=pack\n'+
'chr21 33031596 33033258 item_0 0 -\n'+
'chr21 33033258 33034920 item_1 100 +\n'+
'chr21 33034920 33036582 item_2 200 -\n'+
'chr21 33036582 33038244 item_3 300 +\n'+
'chr21 33038244 33039906 item_4 400 -\n'+
'chr21 33039906 33041570 item_5 500 +\n';
// Optional: trigger any change events if the page listens for them
textarea.dispatchEvent(new Event('change', { bubbles: true }));
textarea.dispatchEvent(new Event('input', { bubbles: true }));
}
},
'load_wig': {
text: 'Load a WIG example',
action () {
// Add text to the textarea
const textarea = document.querySelector('textarea[name="hgct_customText"]');
if (textarea.value.trim() === '') {
textarea.value = 'browser position chr21:33031596-33041570\n';
}
textarea.value += 'track type=wiggle_0 priority="110" name="Wiggle variableStep" '+
'visibility=full autoScale=off viewLimits=5.0:25.0 color=255,200,0 '+
'yLineMark=11.76 yLineOnOff=on\n'+
'variableStep chrom=chr21 span=1108\n'+
'33031597 10.0\n'+
'33032705 12.5\n'+
'33033813 15.0\n'+
'33034921 17.5\n'+
'33036029 20.0\n'+
'33037137 17.5\n'+
'33038245 15.0\n'+
'33039353 12.5\n'+
'33040461 10.0\n';
// Optional: trigger any change events if the page listens for them
textarea.dispatchEvent(new Event('change', { bubbles: true }));
textarea.dispatchEvent(new Event('input', { bubbles: true }));
}
},
'submit': {
text: 'Submit & continue',
action() {
// Save the tour so it continues after page reload
sessionStorage.setItem('customTrackTourActive', 'true');
sessionStorage.setItem('customTrackTourStep', 'after-submit');
// Click the submit button
const submitButton = document.getElementById('Submit');
submitButton.click();
}
},
'end': {
action() {
hideMenu('#help > ul');
return this.complete();
},
//classes: 'shepherd-button-secondary',
text: 'Finish'
}
};
// Function to disable drop-downs, button clicks, and text inputs
function toggleSelects(containerId, enabled) {
const container = document.getElementById(containerId);
const selectors = ['select', 'button', 'input[type="radio"]',
'input[type="submit"]', 'input[type="checkbox"]',
'input[type="text"]'
];
container.querySelectorAll(selectors).forEach(sel => {
if (enabled) {
sel.style.pointerEvents = '';
sel.style.opacity = '';
sel.tabIndex = 0;
} else {
sel.style.pointerEvents = 'none'; // blocks mouse interaction
sel.style.opacity = '1'; // keep visual styling normal
sel.tabIndex = -1; // skip from keyboard nav
}
});
}
// Function to keep menus visible using a selector
function keepMenuVisible(selector) {
const menu = document.querySelector(selector);
//Make sure the drop-down is visibile
menu.style.display = 'block';
menu.style.visibility = 'visible';
// function to keep the menu visibile
const makeVisible = () => {
menu.style.display = 'block';
menu.style.visibility = 'visible';
};
const events = ['mouseover', 'mouseout', 'mouseenter', 'mouseleave', 'mousemove'];
// Add event listeners to keep the menu open
events.forEach(event => {
menu.addEventListener(event, makeVisible);
});
// Add event listeners to the elements of the menu list
menu.querySelectorAll('li').forEach(function(item) {
events.forEach(event => {
item.addEventListener(event, makeVisible);
});
});
}
// Function to hide the menu
function hideMenu(selector) {
const menu = document.querySelector(selector);
menu.style.display = 'none';
}
// Function to add steps to the customTrackTour
function customTrackSteps() {
customTrackTour.addStep({
title: 'Adding custom data to the Genome Browser',
text:
'In this tutorial, we '+
'will explore how to configure custom tracks '+
'in the various formats '+
'available for a track.
'+
'For a stable and permanent visualization, please consider '+
'creating a track hub. If you require hosting space, '+
'the UCSC Genome Browser now provides 10Gb of '+
'free hosting space '+
'for each user.',
buttons: [tutorialButtons.quit, tutorialButtons.next],
id: 'intro'
});
customTrackTour.addStep({
title: 'Selecting the genome assembly',
text:
'By default, your most recently viewed assembly is selected. '+
'Alter the drop-down menus to change the genome assembly.',
buttons: [tutorialButtons.back, tutorialButtons.next],
attachTo:
{
element: '#genome-selection-table',
on: 'bottom'
},
id: 'genome-select'
});
customTrackTour.addStep({
title: 'Text-based custom tracks',
text:
- 'The simplest way to view a custom track is to paste the '+
+ 'The simplest way to view a custom track is to paste '+
'the track and data lines in the dialog box. '+
'A custom track consists of three items:'+
'