1e82a3b6411cc32e625b36911f4949b552ffba3d jrobinso Mon Sep 15 19:05:40 2025 -0700 Add igv configuration menu to name panel. Also expose igv.js createIcon function diff --git src/hg/js/igvFileHelper.js src/hg/js/igvFileHelper.js index 6794987c226..eb01d4cfc6c 100644 --- src/hg/js/igvFileHelper.js +++ src/hg/js/igvFileHelper.js @@ -374,70 +374,98 @@ } } }); }); /** * Update the track names in the left hand column of the IGV row in the image table. */ function updateTrackNames() { // Add track names to the left hand column. const allTracks = igvBrowser.findTracks(t => t.type); let top = 0; document.getElementById('igv_namediv').innerHTML = ""; // Clear any existing content for (let track of allTracks) { - const trackLabelDiv = document.createElement('div'); - trackLabelDiv.setAttribute('data-track-id', track.id); // Set the track ID attribute - trackLabelDiv.textContent = track.name; // Set the track name as the label - trackLabelDiv.style.marginBottom = '5px'; // Optional: Add spacing between labels - trackLabelDiv.style.position = 'absolute'; // Use absolute positioning - trackLabelDiv.style.top = `${top}px`; // Position the element at the current value of "top" - trackLabelDiv.style.right = '5px'; // Set a fixed width for the label div - trackLabelDiv.style.textAlign = 'right'; // Right-justify the text - document.getElementById('igv_namediv').appendChild(trackLabelDiv); - trackLabelDiv.addEventListener('contextmenu', (e) => { + if('sequence' !== track.type) { + const labelContainer = document.createElement('div'); + labelContainer.style.position = 'absolute'; // Use relative positioning + labelContainer.style.top = `${top}px`; // Position the element at the current value of "top" + labelContainer.style.left = '0'; + labelContainer.style.right = '0'; // span full width of the enclosing td via igv_namediv + labelContainer.style.width = '100%'; // optional, for clarity + + const gearDiv = document.createElement('div'); + gearDiv.style.position = 'absolute'; + gearDiv.style.left = '5px'; + gearDiv.style.width = '15px'; + gearDiv.style.height = '15px'; + gearDiv.style.maxWidth = '15px'; + gearDiv.style.maxHeight = '15px'; + gearDiv.style.overflow = 'hidden'; + + const cog = igv.createIcon('cog', 'grey'); + // Ensure the underlying SVG is 15x15 + const svg = cog.tagName && cog.tagName.toLowerCase() === 'svg' ? cog : cog.querySelector('svg'); + if (svg) { + svg.setAttribute('width', '15'); + svg.setAttribute('height', '1'); + svg.style.width = '15px'; + svg.style.height = '15px'; + } + + gearDiv.appendChild(cog); + gearDiv.setAttribute('data-track-id', track.id); // Set the track ID attribute + labelContainer.appendChild(gearDiv); + gearDiv.addEventListener("click", (e) => { e.stopPropagation(); e.preventDefault(); const trackId = e.currentTarget.getAttribute('data-track-id'); const matchingTracks = igvBrowser.findTracks(t => t.id === trackId); if (matchingTracks.length > 0) { const trackView = matchingTracks[0].trackView; trackView.trackGearPopup.presentMenuList( trackView, igvBrowser.menuUtils.trackMenuItemList(trackView), igvBrowser.config); } }); + const trackLabelDiv = document.createElement('div'); + trackLabelDiv.textContent = track.name; // Set the track name as the label + trackLabelDiv.style.right = '5px'; // Set a fixed width for the label div + trackLabelDiv.style.textAlign = 'right'; // Right-justify the text + labelContainer.appendChild(trackLabelDiv); + + document.getElementById('igv_namediv').appendChild(labelContainer); + } top += track.trackView.viewports[0].viewportElement.clientHeight; // Adjust top for the next element } } function insertIGVRow() { - // Insert the IGV row into the image table. const imgTbl = document.getElementById('imgTbl'); const tbody = imgTbl.querySelector('tbody'); const igvRow = document.createElement('tr'); igvRow.id = "tr_igv"; igvRow.innerHTML = `
-
+
`; tbody.appendChild(igvRow); return igvRow; } /** * Create an IGV browser instance and insert it into the image table as a new row. The IGV browser essentially becomes * a track in the UCSC browser context. This function is called when the user adds the first IGV track, or * the igv session is restored on page reload. * * @param config -- The IGV browser configuration object. Must include a reference genome, but might also include