// @name YouTube Sidebar Always Expanded (Updated - No Video or Search Pages)
// @namespace http://tampermonkey.net/
// @version 0.5
// @description Attempts to keep the YouTube sidebar expanded, excluding video watch pages and search results pages.
// @author Your Name
// @match https://www.youtube.com/*
// @grant none
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// Function to expand the sidebar
function expandSidebar() {
// IMPORTANT: Always check if the current page is a video watch page or a search results page.
// This prevents the script from trying to expand the sidebar in unwanted contexts.
const isExcludedPage = window.location.pathname.startsWith('/watch') ||
window.location.pathname.startsWith('/results');
if (isExcludedPage) {
console.log('YouTube Sidebar: expandSidebar called on an excluded page (video or search results). Skipping expansion.');
return; // Do nothing if on an excluded page
}
// Find the main application element which often controls sidebar visibility state
const ytdApp = document.querySelector('ytd-app');
// Find the guide button (hamburger menu icon) which toggles the sidebar
// This selector is generally stable for the guide button.
const guideButton = document.querySelector('yt-icon-button#guide-button');
if (!ytdApp) {
console.log('YouTube Sidebar: ytd-app element not found.');
return;
}
if (!guideButton) {
console.log('YouTube Sidebar: Guide button (#guide-button) not found.');
return;
}
// Check the current state of the sidebar.
// YouTube often uses the 'guide-persistent-and-visible' attribute on ytd-app
// when the full sidebar is open.
const isSidebarExpanded = ytdApp.hasAttribute('guide-persistent-and-visible');
// If the sidebar is not expanded, click the guide button to expand it.
if (!isSidebarExpanded) {
// Check if the button is visible and clickable
if (guideButton.offsetParent !== null) { // offsetParent checks if element is in the document and visible
guideButton.click();
console.log('YouTube Sidebar: Clicked guide button to expand sidebar.');
} else {
console.log('YouTube Sidebar: Guide button found but not visible/clickable.');
}
} else {
console.log('YouTube Sidebar: Sidebar is already expanded.');
}
}
// Use a MutationObserver to watch for changes in the DOM.
// This is crucial because YouTube's UI loads dynamically, changes on navigation,
// and can be modified by user actions or other scripts.
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
// We are interested in attribute changes on 'ytd-app' which indicate layout changes.
if (mutation.type === 'attributes' && mutation.target.tagName === 'YTD-APP') {
console.log('YouTube Sidebar: ytd-app attributes changed, re-checking sidebar state.');
// Add a small delay to ensure the UI has settled after a change
setTimeout(expandSidebar, 100);
}
// Also, check for childList changes on the body or ytd-app to catch major UI re-renders.
// This is a broader check but can be useful if the structure changes significantly.
if (mutation.type === 'childList' && (mutation.target === document.body || mutation.target.tagName === 'YTD-APP')) {
// A small delay might be needed to ensure the DOM is fully rendered after a change
setTimeout(expandSidebar, 200);
}
});
});
// Start observing the document body for changes.
// We observe subtree to catch changes within the entire application layout.
observer.observe(document.body, {
attributes: true, // Watch for attribute changes
childList: true, // Watch for direct child additions/removals
subtree: true // Watch for changes in the entire subtree
});
// Initial expansion attempt when the script first loads.
// A slight delay ensures YouTube's core UI elements are present.
window.addEventListener('load', () => {
setTimeout(expandSidebar, 750); // Wait 0.75 seconds after page load
});
// Listen for URL changes, which signifies navigation within YouTube's Single Page Application (SPA).
// This ensures the sidebar is re-checked/expanded when navigating between videos or pages.
let lastUrl = location.href;
new MutationObserver(() => {
if (location.href !== lastUrl) {
lastUrl = location.href;
console.log('YouTube Sidebar: URL changed, re-checking sidebar state after navigation.');
// Only attempt to expand if the new URL is NOT an excluded page.
// The expandSidebar function itself also has this check for robustness.
const isExcludedPage = window.location.pathname.startsWith('/watch') ||
window.location.pathname.startsWith('/results');
if (!isExcludedPage) {
setTimeout(expandSidebar, 750); // Re-check after navigation with a slightly longer delay
} else {
console.log('YouTube Sidebar: New URL is an excluded page. Sidebar expansion script remains disabled for this page.');
}
}
}).observe(document.body, {subtree: true, childList: true}); // Observe body for URL changes
})();