YouTube: Search results in Grid view

See more results in one go, without irrelevant results, such as 'People also watched' and 'For you', in the way.

Verzia zo dňa 25.06.2024. Pozri najnovšiu verziu.

// ==UserScript==
// @name              YouTube: Search results in Grid view
// @namespace         https://greasyfork.org/users/1166888-pedro
// @match             https://www.youtube.com/*
// @version           2024.6.25.1
// @author            Pedro
// @icon              https://i.imgur.com/DWVSLcD.png
// @description       See more results in one go, without irrelevant results, such as 'People also watched' and 'For you', in the way.
// @contributionURL   https://www.paypal.com/paypalme/pdrmmi
// @grant             GM_registerMenuCommand
// @grant             GM_setValue
// @grant             GM_getValue
// @compatible        Chrome
// @compatible        Safari
// @compatible        Firefox
// @license           MIT
// ==/UserScript==
GM_registerMenuCommand('Settings', settingsMenu);

function settingsMenu() {
    const menu = document.createElement('settings-menu');
    document.documentElement.appendChild(menu);
    menu.insertAdjacentHTML('afterbegin', `
    <div>
      <header>
        <span>Settings</span>
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
          <path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm4.3 14.3c-.39.39-1.02.39-1.41 0L12 13.41 9.11 16.3c-.39.39-1.02.39-1.41 0-.39-.39-.39-1.02 0-1.41L10.59 12 7.7 9.11c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0L12 10.59l2.89-2.89c.39-.39 1.02-.39 1.41 0 .39.39.39 1.02 0 1.41L13.41 12l2.89 2.89c.38.38.38 1.02 0 1.41z"></path>
        </svg>
      </header>
      <label>
        <span>Maximum number of columns </span>
        <input type="number" id="maxNumOfColumns" value="${maxNumOfColumns}">
      </label>
      <label>
        <span>Minimum column width (px)</span>
        <input type="number" id="columnMinWidth" value="${columnMinWidth}">
      </label>
      <label>
        <span>Hide right sidebar</span>
        <input type="checkbox" id="hideRightSidebar" ${GM_getValue('hideRightSidebar') ? 'checked' : ''}>
      </label>
      <style>
        settings-menu svg {
          color: var(--background-3);
          width: 24px;
          height: 24px;
          transition: 0.4s;
          color: var(--text);
          opacity: .7;
        }

        settings-menu svg:hover {
          transform: rotate(-90deg);
          opacity: 1;
        }

        settings-menu svg:active {
          transform: scale(1.5);
        }

        settings-menu div {
          margin: 10px;
        }

        settings-menu {
          width: 310px;
          position: fixed;
          background: var(--background);
          top: 20px;
          right: 20px;
          z-index: 9999;
          color: var(--text);
          font-size: 1.4rem;
          border-radius: 20px;
          box-shadow: 0 4px 32px 0 rgba(0, 0, 0, 0.3);
          font-weight: 400;
          border: 1px solid var(--border);
        }

        settings-menu header {
          font-size: 1.7rem;
          font-weight: 500;
        }

        settings-menu header,
        settings-menu label {
          padding: 6px;
          display: flex;
          align-items: center;
        }

        settings-menu svg,
        settings-menu label {
          cursor: pointer;
        }

        settings-menu span {
          flex-grow: 1;
        }

        settings-menu [type="number"] {
          font-family: "Roboto";
          font-size: inherit;
          box-sizing: border-box;
          border: none;
          width: 60px;
          height: 30px;
          background: var(--background-2);
          color: inherit;
          outline: none;
          border-radius: 6px;
          padding: 0 3px;
        }

        settings-menu [type="number"]::-webkit-inner-spin-button {
          height: 30px;
        }

        settings-menu [type="checkbox"] {
          appearance: none;
          -webkit-tap-highlight-color: transparent;
          position: relative;
          border: 0;
          outline: 0;
          width: 37.5px;
          height: 24px;
          cursor: pointer;
        }

        settings-menu [type="checkbox"]:after {
          content: "";
          width: 100%;
          height: 100%;
          display: inline-block;
          border-radius: 100px;
          clear: both;
          background: var(--background-2);
          transition: background-color linear 0.08s;
        }

        settings-menu [type="checkbox"]:checked:after {
          background: #1db954;
        }

        settings-menu [type="checkbox"]:before {
          content: "";
          height: 19.5px;
          width: 19.5px;
          display: block;
          position: absolute;
          left: 0;
          top: 2px;
          border-radius: 50%;
          background: #fff;
          box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0 2px 3px 0 rgba(0, 0, 0, 0.2);
          transform: translateX(2px);
          transition: transform linear 0.1s, background-color linear 0.08s;
        }

        settings-menu [type="checkbox"]:checked:before {
          transform: translateX(80%);
          transition: transform linear 0.1s, background-color linear 0.08s;
        }

        @media (prefers-color-scheme: dark) {
          :root {
            color-scheme: dark;
            --text: #f1f1f1;
            --background: #000;
            --background-2: rgba(255, 255, 255, .1);
            --border: rgba(255, 255, 255, .2);
          }
        }

        @media (prefers-color-scheme: light) {
          :root {
            --text: #030303;
            --background: #fff;
            --background-2: rgba(0, 0, 0, .1);
          }
        }
      </style>
    </div>`);

    menu.addEventListener('change', function(e) {
        if (e.target.type === 'number') {
            GM_setValue(e.target.id, e.target.value);
            if (e.target.id == 'maxNumOfColumns') maxNumOfColumns = GM_getValue('maxNumOfColumns');
            else columnMinWidth = GM_getValue('columnMinWidth');
        } else {
            GM_setValue(e.target.id, e.target.checked);
        }

        handleResize();
    });

    menu.querySelector('svg').addEventListener('click', function() {
        menu.remove();
    });
}

let maxNumOfColumns = GM_getValue('maxNumOfColumns') || 6;
let columnMinWidth = GM_getValue('columnMinWidth') || 326;
const div = document.createElement('div');
div.style = 'position: absolute; width: calc(100% - 32px - var(--sidebarWidth, 0px))';

document.addEventListener('yt-navigate-finish', function() {
    const pm = document.getElementById('page-manager');
    pm.style.position = 'relative';
    pm.appendChild(div);

    new ResizeObserver(function() {
        handleResize();
    }).observe(div);
}, {once: true});

document.addEventListener('yt-navigate-finish', function() {
    if (/@.*search/.test(window.location.href)) {
        document.documentElement.classList.add('channelSearch');
    } else {
        document.documentElement.classList.remove('channelSearch');
    }
});

function handleResize() {
    let hasRun;

    for (let i = maxNumOfColumns; i > 0; i--) {
        if (div.clientWidth / i >= columnMinWidth) {
            document.documentElement.style.setProperty('--numOfColumns', i);
            hasRun = 1;
            break;
        }
    }

    if (!hasRun) document.documentElement.style.setProperty('--numOfColumns', 1);
}

const sheet = document.createElement('style');
document.documentElement.appendChild(sheet);
sheet.textContent = `
ytd-search {
  padding-left: 16px !important;
  padding-right: 16px !important;
}
ytd-search ytd-search-pyv-renderer,
ytd-search ytd-ad-slot-renderer,
ytd-search .metadata-snippet-container-one-line.ytd-video-renderer,
ytd-search .metadata-snippet-container.ytd-video-renderer,
ytd-search #description-text.ytd-video-renderer,
ytd-search #description.ytd-channel-renderer,
ytd-search #list,
ytd-search #expandable-metadata.ytd-video-renderer:not(:empty),
ytd-search ytd-exploratory-results-renderer.ytd-item-section-renderer,
ytd-search ytd-horizontal-card-list-renderer.ytd-item-section-renderer:not(:first-child),
ytd-search ytd-reel-shelf-renderer.ytd-item-section-renderer,
ytd-search ytd-shelf-renderer.ytd-item-section-renderer,
ytd-search #channel-name.ytd-video-renderer,
ytd-search #separator.ytd-video-meta-block {
  display: none !important;
}
ytd-search #view-more.ytd-playlist-renderer,
ytd-search #metadata.ytd-video-meta-block,
ytd-search #byline-container[hidden] {
  display: block !important;
}
ytd-search #container.ytd-search {
  max-width: calc(var(--numOfColumns) * (var(--ytd-rich-grid-item-max-width) + var(--ytd-rich-grid-item-margin)) + var(--sidebarWidth, 0px));
  min-width: calc(var(--sidebarWidth) + var(--ytd-rich-grid-item-max-width));
}
ytd-search #header.ytd-search,
ytd-search ytd-two-column-search-results-renderer,
ytd-search #primary.ytd-two-column-search-results-renderer {
  max-width: 100% !important;
}
ytd-search #contents > ytd-item-section-renderer,
ytd-search #contents > ytd-item-section-renderer > #contents {
  display: contents;
}
ytd-search ytd-item-section-renderer[can-show-more]:after {
  /* Fix for elements appearing in wrong spots */
  content: "";
  width: 100%;
  min-height: 7000px;
}
ytd-search #contents.ytd-section-list-renderer {
  display: flex;
  flex-wrap: wrap;
}
ytd-search #contents > .ytd-item-section-renderer {
  margin-left: calc(var(--ytd-rich-grid-item-margin)/2);
  margin-right: calc(var(--ytd-rich-grid-item-margin)/2);
  width: calc(100%/var(--numOfColumns) - var(--ytd-rich-grid-item-margin) - 0.01px);
  margin-bottom: 24px;
}
ytd-search ytd-movie-renderer {
  width: calc(200%/var(--numOfColumns) - var(--ytd-rich-grid-item-margin) - 0.01px) !important;
}
ytd-search yt-did-you-mean-renderer,
ytd-search yt-showing-results-for-renderer,
ytd-search ytd-thumbnail.ytd-video-renderer,
ytd-search ytd-playlist-thumbnail.ytd-radio-renderer,
ytd-search ytd-playlist-thumbnail.ytd-playlist-renderer,
ytd-search ytd-playlist-thumbnail.ytd-show-renderer {
  min-width: 100% !important;
}
ytd-search ytd-playlist-thumbnail.ytd-show-renderer {
  flex: 0 !important;
}
ytd-search ytd-playlist-thumbnail.ytd-playlist-renderer {
  margin: 0 !important;
}
ytd-search .thumbnail-container.ytd-movie-renderer {
  min-width: 0 !important;
}
ytd-search ytd-item-section-renderer[top-spacing-zero]:first-child #contents.ytd-item-section-renderer .ytd-item-section-renderer:first-child:not(yt-did-you-mean-renderer):not(yt-showing-results-for-renderer) {
  margin-top: 16px;
}
ytd-search #dismissible.ytd-video-renderer,
ytd-search ytd-radio-renderer,
ytd-search ytd-playlist-renderer,
ytd-search #content-section.ytd-channel-renderer,
ytd-search #info-section.ytd-channel-renderer,
ytd-search ytd-show-renderer {
  flex-direction: column;
}
ytd-search #video-title {
  font-size: 1.6rem !important;
  line-height: 2.2rem !important;
  font-weight: 500 !important;
}
ytd-search h3:not(.ytd-movie-renderer) {
  margin: 12px 0 4px 0 !important;
}
ytd-search #channel-title.ytd-channel-renderer {
  font-size: 1.6rem;
  line-height: 2.2rem;
  font-weight: 500;
  margin: 12px 0 4px 0;
  align-self: center;
}
ytd-search ytd-video-meta-block:not([rich-meta]) .ytd-video-meta-block:is(#metadata-line, #byline-container),
ytd-search #metadata.ytd-channel-renderer {
  font-size: 1.4rem;
  line-height: 2rem;
  max-height: 3.6rem;
}
ytd-search #content.ytd-playlist-renderer,
ytd-search #content.ytd-radio-renderer,
ytd-search #info-section.ytd-channel-renderer {
  flex-basis: 100%;
}
ytd-search #info.ytd-channel-renderer {
  padding: 0 0px 16px 0;
  text-align: center;
}
ytd-search .ytd-channel-renderer yt-formatted-string {
  text-align: center !important;
}
ytd-search #avatar-section.ytd-channel-renderer {
  min-width: 100% !important;
}
ytd-search .ytd-channel-renderer:is(#buttons, #purchase-button, #subscribe-button) {
  padding: 0 !important;
  align-self: center;
}
ytd-search #badges.ytd-video-renderer {
  margin: 4px 0 0 0;
}
ytd-search .text-wrapper.ytd-video-renderer {
  position: relative;
  width: 100%;
}
ytd-search #channel-thumbnail.ytd-video-renderer {
  position: absolute;
  top: 12px;
}
ytd-search yt-img-shadow.ytd-video-renderer img.yt-img-shadow {
  width: 36px;
  height: 36px;
}
ytd-search ytd-video-renderer[use-search-ui] #channel-info.ytd-video-renderer {
  padding: 0;
}
body[dir="ltr"] ytd-search ytd-menu-renderer.ytd-video-renderer {
  position: absolute;
  right: -12px;
  margin: 4px 0 0 0;
}
body[dir="ltr"] ytd-search #title-wrapper.ytd-video-renderer {
  padding-right: 24px;
}
body[dir="ltr"] ytd-search .ytd-video-renderer:is(#title-wrapper, #channel-name, #badges, #buttons),
body[dir="ltr"] ytd-search ytd-video-meta-block.ytd-video-renderer {
  padding-left: 48px;
}
body[dir="rtl"] ytd-search ytd-menu-renderer.ytd-video-renderer {
  position: absolute;
  left: -12px;
  margin: 4px 0 0 0;
}
body[dir="rtl"] ytd-search #title-wrapper.ytd-video-renderer {
  padding-left: 24px;
}
body[dir="rtl"] ytd-search .ytd-video-renderer:is(#title-wrapper, #channel-name, #badges, #buttons),
body[dir="rtl"] ytd-search ytd-video-meta-block.ytd-video-renderer {
  padding-right: 48px;
}
.channelSearch #description-text.ytd-video-renderer,
.channelSearch #list.ytd-playlist-renderer {
  display: none;
}
.channelSearch #metadata.ytd-video-meta-block,
.channelSearch #view-more.ytd-playlist-renderer {
  display: block;
}
.channelSearch ytd-browse[page-subtype=channels] ytd-two-column-browse-results-renderer {
  width: calc(100% - 32px) !important;
  max-width: calc(var(--numOfColumns) * (var(--ytd-rich-grid-item-max-width) + var(--ytd-rich-grid-item-margin))) !important;
}
.channelSearch #contents.ytd-item-section-renderer,
.channelSearch ytd-item-section-renderer.ytd-section-list-renderer {
  display: contents;
}
.channelSearch #contents.ytd-section-list-renderer {
  display: flex;
  flex-wrap: wrap;
}
.channelSearch ytd-video-renderer,
.channelSearch ytd-playlist-renderer,
.channelSearch ytd-show-renderer {
  width: calc(100% / var(--numOfColumns) - var(--ytd-rich-grid-item-margin) - 0.01px);
  margin-left: calc(var(--ytd-rich-grid-item-margin) / 2);
  margin-right: calc(var(--ytd-rich-grid-item-margin) / 2);
  margin-bottom: 24px;
}
.channelSearch ytd-thumbnail.ytd-video-renderer,
.channelSearch ytd-playlist-thumbnail.ytd-playlist-renderer,
.channelSearch ytd-playlist-thumbnail.ytd-show-renderer {
  width: 100% !important;
  height: 100% !important;
  flex: 0 !important;
}
.channelSearch ytd-thumbnail.ytd-video-renderer:before,
.channelSearch ytd-playlist-thumbnail.ytd-playlist-renderer:before,
.channelSearch ytd-playlist-thumbnail.ytd-show-renderer:before {
  display: block;
  content: "";
  padding-top: 56.11%;
}
.channelSearch #dismissible.ytd-video-renderer,
.channelSearch ytd-playlist-renderer,
.channelSearch ytd-show-renderer {
  flex-direction: column;
}
.channelSearch #video-title {
  font-size: 1.6rem !important;
  line-height: 2.2rem !important;
  font-weight: 500 !important;
}
.channelSearch ytd-video-meta-block:not([rich-meta]) .ytd-video-meta-block:is(#byline-container, #metadata-line) {
  font-size: 1.4rem;
  line-height: 2rem;
  max-height: 2rem;
}
.channelSearch .title-and-badge.ytd-video-renderer,
.channelSearch h3:is(.ytd-playlist-renderer, .ytd-show-renderer) {
  margin: 12px 0 4px 0;
}
.channelSearch #badges.ytd-video-renderer {
  margin: 4px 0 0 0;
}
.channelSearch #content.ytd-playlist-renderer {
  flex-basis: 100%;
}
.channelSearch .text-wrapper.ytd-video-renderer {
  max-width: 100%;
}
.channelSearch body[dir="ltr"] ytd-menu-renderer.ytd-video-renderer {
  position: absolute;
  right: -12px;
  margin-top: 4px;
}
.channelSearch body[dir="ltr"] #meta.ytd-video-renderer {
  padding-right: 24px;
}
.channelSearch body[dir="rtl"] ytd-menu-renderer.ytd-video-renderer {
  position: absolute;
  left: -12px;
  margin-top: 4px;
}
.channelSearch body[dir="rtl"] #meta.ytd-video-renderer {
  padding-left: 24px;
}

${GM_getValue('hideRightSidebar') ? `
ytd-secondary-search-container-renderer {
  display: none !important;
}
`
:
`
@media (min-width: 1091px) {
  #page-manager:has(ytd-search[role][has-secondary-content]) {
    --sidebarWidth: 425px;
  }
}
`}
`;