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.

目前为 2024-06-08 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name YouTube: Search results in Grid view
  3. // @namespace https://greasyfork.org/users/1166888-pedro
  4. // @match https://www.youtube.com/*
  5. // @version 2024.6.8
  6. // @author Pedro
  7. // @description See more results in one go, without irrelevant results, such as 'People also watched' and 'For you', in the way.
  8. // @grant GM_registerMenuCommand
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @compatible Chrome
  12. // @compatible Safari
  13. // @compatible Firefox
  14. // @license MIT
  15. // ==/UserScript==
  16. GM_registerMenuCommand('Settings', settingsMenu);
  17.  
  18. function settingsMenu() {
  19. const menu = document.createElement('settings-menu');
  20. document.documentElement.appendChild(menu);
  21. menu.insertAdjacentHTML('afterbegin', `
  22. <div>
  23. <header>
  24. <span>Settings</span>
  25. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
  26. <path d="M0 0h24v24H0V0z" fill="none" opacity=".87"></path>
  27. <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>
  28. </svg>
  29. </header>
  30. <label>
  31. <span>Videos per row</span>
  32. <input type="number" id="videosPerRow">
  33. </label>
  34. <label>
  35. <span>Hide right sidebar</span>
  36. <input type="checkbox" id="hideRightSidebar">
  37. </label>
  38. <style>
  39. settings-menu svg {
  40. color: var(--background-3);
  41. width: 24px;
  42. height: 24px;
  43. transition: 0.4s;
  44. }
  45.  
  46. settings-menu svg:hover {
  47. color: inherit;
  48. transform: rotate(-90deg);
  49. }
  50.  
  51. settings-menu svg:active {
  52. transform: scale(1.5);
  53. }
  54.  
  55. settings-menu div {
  56. margin: 10px;
  57. }
  58.  
  59. settings-menu {
  60. width: 225px;
  61. position: fixed;
  62. background: var(--background);
  63. top: 20px;
  64. right: 20px;
  65. z-index: 9999;
  66. color: var(--text);
  67. font-size: 1.4rem;
  68. border-radius: 12px;
  69. box-shadow: 0 4px 32px 0 rgba(0, 0, 0, 0.1);
  70. font-weight: 400;
  71. border: 1px solid var(--border);
  72. }
  73.  
  74. settings-menu header {
  75. font-size: 1.7rem;
  76. font-weight: 500
  77. }
  78.  
  79. settings-menu header,
  80. settings-menu label {
  81. padding: 6px;
  82. display: flex;
  83. align-items: center;
  84. }
  85.  
  86. settings-menu svg,
  87. settings-menu label {
  88. cursor: pointer;
  89. }
  90.  
  91. settings-menu span {
  92. flex-grow: 1;
  93. }
  94.  
  95. settings-menu [type="number"] {
  96. font-family: "Roboto";
  97. font-size: inherit;
  98. box-sizing: border-box;
  99. border: none;
  100. width: 60px;
  101. height: 30px;
  102. background: var(--background-2);
  103. color: inherit;
  104. outline: none;
  105. border-radius: 5px;
  106. padding: 0 3px;
  107. }
  108.  
  109. settings-menu [type="number"]::-webkit-inner-spin-button {
  110. height: 30px;
  111. }
  112.  
  113. settings-menu [type="checkbox"] {
  114. appearance: none;
  115. -webkit-tap-highlight-color: transparent;
  116. position: relative;
  117. border: 0;
  118. outline: 0;
  119. width: 37.5px;
  120. height: 24px;
  121. cursor: pointer;
  122. }
  123.  
  124. settings-menu [type="checkbox"]:after {
  125. content: "";
  126. width: 100%;
  127. height: 100%;
  128. display: inline-block;
  129. border-radius: 100px;
  130. clear: both;
  131. background: var(--toggle-button-track);
  132. transition: background-color linear 0.08s;
  133. }
  134.  
  135. settings-menu [type="checkbox"]:checked:after {
  136. background: #1db954;
  137. }
  138.  
  139. settings-menu [type="checkbox"]:before {
  140. content: "";
  141. height: 19.5px;
  142. width: 19.5px;
  143. display: block;
  144. position: absolute;
  145. left: 0;
  146. top: 2px;
  147. border-radius: 50%;
  148. background: #fff;
  149. box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0 2px 3px 0 rgba(0, 0, 0, 0.2);
  150. transform: translateX(2px);
  151. transition: transform linear 0.1s, background-color linear 0.08s;
  152. }
  153.  
  154. settings-menu [type="checkbox"]:checked:before {
  155. transform: translateX(80%);
  156. transition: transform linear 0.1s, background-color linear 0.08s;
  157. }
  158.  
  159. @media (prefers-color-scheme: dark) {
  160. :root {
  161. color-scheme: dark;
  162. --text: #f1f1f1;
  163. --background: #121212;
  164. --background-2: #272727;
  165. --background-3: #999;
  166. --toggle-button-track: rgba(113, 113, 113, 0.4);
  167. --border: rgba(255, 255, 255, 0.2)
  168. }
  169. }
  170.  
  171. @media (prefers-color-scheme: light) {
  172. :root {
  173. --text: #030303;
  174. --background: #fff;
  175. --background-2: #e5e5e5;
  176. --background-3: #666;
  177. --toggle-button-track: rgba(144, 144, 144, 0.4);
  178. }
  179. }
  180. </style>
  181. </div>`);
  182.  
  183. menu.addEventListener('change', function(event) {
  184. if (event.target.type === 'number') {
  185. GM_setValue('videosPerRow', event.target.value);
  186. document.documentElement.style.setProperty('--videos-per-row', event.target.value);
  187. } else {
  188. GM_setValue('hideRightSidebar', event.target.checked);
  189. document.documentElement.classList.toggle('hideRightSidebar');
  190. }
  191. });
  192.  
  193. menu.querySelector('#videosPerRow').value = GM_getValue('videosPerRow') || 5;
  194. menu.querySelector('#hideRightSidebar').checked = GM_getValue('hideRightSidebar');
  195. menu.querySelector('svg').addEventListener('click', function() {
  196. menu.remove();
  197. });
  198. }
  199.  
  200. document.documentElement.style.setProperty('--videos-per-row', GM_getValue('videosPerRow') || 5);
  201. if (GM_getValue('hideRightSidebar')) document.documentElement.classList.add('hideRightSidebar');
  202.  
  203. const sheet = document.createElement('style');
  204. document.documentElement.appendChild(sheet);
  205. sheet.textContent = `
  206. ytd-search ytd-search-pyv-renderer,
  207. ytd-search ytd-ad-slot-renderer,
  208. ytd-search .metadata-snippet-container-one-line.ytd-video-renderer,
  209. ytd-search .metadata-snippet-container.ytd-video-renderer,
  210. ytd-search #description-text.ytd-video-renderer,
  211. ytd-search #description.ytd-channel-renderer,
  212. ytd-search #list,
  213. ytd-search #expandable-metadata.ytd-video-renderer:not(:empty),
  214. ytd-search ytd-exploratory-results-renderer.ytd-item-section-renderer,
  215. ytd-search ytd-horizontal-card-list-renderer.ytd-item-section-renderer:not(:first-child),
  216. ytd-search ytd-reel-shelf-renderer.ytd-item-section-renderer,
  217. ytd-search ytd-shelf-renderer.ytd-item-section-renderer,
  218. .hideRightSidebar ytd-search #secondary.ytd-two-column-search-results-renderer {
  219. display: none !important;
  220. }
  221. ytd-search #view-more.ytd-playlist-renderer {
  222. display: block;
  223. }
  224. ytd-search #container.ytd-search {
  225. width: 100%;
  226. max-width: calc(var(--videos-per-row) * (var(--ytd-rich-grid-item-max-width) + var(--ytd-rich-grid-item-margin)));
  227. }
  228. ytd-search #header.ytd-search,
  229. ytd-search ytd-two-column-search-results-renderer,
  230. ytd-search #primary.ytd-two-column-search-results-renderer {
  231. max-width: 100% !important;
  232. }
  233. ytd-search #contents > ytd-item-section-renderer,
  234. ytd-search #contents > ytd-item-section-renderer > #contents {
  235. display: contents;
  236. }
  237. ytd-search ytd-item-section-renderer[can-show-more]:after {
  238. content: "";
  239. width: 100%;
  240. min-height: 7000px;
  241. }
  242. ytd-search #contents.ytd-section-list-renderer {
  243. display: flex;
  244. flex-wrap: wrap;
  245. }
  246. ytd-search #contents > .ytd-item-section-renderer {
  247. margin-left: calc(var(--ytd-rich-grid-item-margin) / 2);
  248. margin-right: calc(var(--ytd-rich-grid-item-margin) / 2);
  249. width: calc(100% / var(--videos-per-row) - var(--ytd-rich-grid-item-margin) - 0.01px);
  250. margin-bottom: 24px;
  251. }
  252. ytd-search ytd-movie-renderer {
  253. width: calc(200% / var(--videos-per-row) - var(--ytd-rich-grid-item-margin) - 0.01px) !important;
  254. }
  255. ytd-search yt-did-you-mean-renderer,
  256. ytd-search yt-showing-results-for-renderer,
  257. ytd-search ytd-thumbnail.ytd-video-renderer,
  258. ytd-search ytd-playlist-thumbnail.ytd-radio-renderer,
  259. ytd-search ytd-playlist-thumbnail.ytd-playlist-renderer,
  260. ytd-search ytd-playlist-thumbnail.ytd-show-renderer {
  261. min-width: 100% !important;
  262. }
  263. ytd-search ytd-playlist-thumbnail.ytd-show-renderer {
  264. flex: 0 !important;
  265. }
  266. ytd-search ytd-playlist-thumbnail.ytd-playlist-renderer {
  267. margin: 0 !important;
  268. }
  269. ytd-search .thumbnail-container.ytd-movie-renderer {
  270. min-width: 0 !important;
  271. }
  272. 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) {
  273. margin-top: 16px;
  274. }
  275. ytd-search #dismissible.ytd-video-renderer,
  276. ytd-search ytd-radio-renderer,
  277. ytd-search ytd-playlist-renderer,
  278. ytd-search #content-section.ytd-channel-renderer,
  279. ytd-search #info-section.ytd-channel-renderer,
  280. ytd-search ytd-show-renderer {
  281. flex-direction: column;
  282. }
  283. ytd-search #video-title {
  284. font-size: 1.6rem !important;
  285. line-height: 2.2rem !important;
  286. font-weight: 500 !important;
  287. }
  288. ytd-search h3:not(.ytd-movie-renderer) {
  289. margin: 12px 0 4px 0 !important;
  290. }
  291. ytd-search #channel-title.ytd-channel-renderer {
  292. font-size: 1.6rem;
  293. line-height: 2.2rem;
  294. font-weight: 500;
  295. margin: 12px 0 4px 0;
  296. align-self: center;
  297. }
  298. ytd-search #content.ytd-playlist-renderer,
  299. ytd-search #content.ytd-radio-renderer,
  300. ytd-search #info-section.ytd-channel-renderer {
  301. flex-basis: 100%;
  302. }
  303. ytd-search #info.ytd-channel-renderer {
  304. padding: 0 0px 16px 0;
  305. text-align: center;
  306. }
  307. ytd-search .ytd-channel-renderer yt-formatted-string {
  308. text-align: center !important;
  309. }
  310. ytd-search #avatar-section.ytd-channel-renderer {
  311. min-width: 100% !important;
  312. }
  313. ytd-search .ytd-channel-renderer:is(#buttons,
  314. ytd-search #purchase-button,
  315. ytd-search #subscribe-button) {
  316. padding: 0 !important;
  317. align-self: center;
  318. }
  319. ytd-search .text-wrapper.ytd-video-renderer {
  320. position: relative;
  321. width: 100%;
  322. }
  323. ytd-search #channel-thumbnail.ytd-video-renderer {
  324. position: absolute;
  325. top: 12px;
  326. }
  327. ytd-search yt-img-shadow.ytd-video-renderer img.yt-img-shadow {
  328. width: 36px;
  329. height: 36px;
  330. }
  331. ytd-search #meta.ytd-video-renderer {
  332. display: contents;
  333. }
  334. ytd-search ytd-video-meta-block.ytd-video-renderer,
  335. ytd-search #buttons.ytd-video-renderer {
  336. order: 2;
  337. }
  338. ytd-search #badges.ytd-video-renderer {
  339. order: 2;
  340. margin: 4px 0 0 0;
  341. }
  342. ytd-search ytd-video-renderer[use-search-ui] #channel-info.ytd-video-renderer {
  343. padding: 0;
  344. }
  345. body[dir="ltr"] ytd-search ytd-menu-renderer.ytd-video-renderer {
  346. position: absolute;
  347. right: -12px;
  348. margin: 4px 0 0 0;
  349. }
  350. body[dir="ltr"] ytd-search #title-wrapper.ytd-video-renderer {
  351. padding-right: 24px;
  352. }
  353. body[dir="ltr"] ytd-search .ytd-video-renderer:is(#title-wrapper,
  354. body[dir="ltr"] ytd-search #channel-name,
  355. body[dir="ltr"] ytd-search #badges,
  356. body[dir="ltr"] ytd-search #buttons),
  357. body[dir="ltr"] ytd-search ytd-video-meta-block.ytd-video-renderer {
  358. padding-left: 48px;
  359. }
  360. body[dir="rtl"] ytd-search ytd-menu-renderer.ytd-video-renderer {
  361. position: absolute;
  362. left: -12px;
  363. margin: 4px 0 0 0;
  364. }
  365. body[dir="rtl"] ytd-search #title-wrapper.ytd-video-renderer {
  366. padding-left: 24px;
  367. }
  368. body[dir="rtl"] ytd-search .ytd-video-renderer:is(#title-wrapper,
  369. body[dir="rtl"] ytd-search #channel-name,
  370. body[dir="rtl"] ytd-search #badges,
  371. body[dir="rtl"] ytd-search #buttons),
  372. body[dir="rtl"] ytd-search ytd-video-meta-block.ytd-video-renderer {
  373. padding-right: 48px;
  374. }
  375. .channelSearch #description-text.ytd-video-renderer,
  376. .channelSearch #list.ytd-playlist-renderer {
  377. display: none;
  378. }
  379. .channelSearch #metadata.ytd-video-meta-block,
  380. .channelSearch #view-more.ytd-playlist-renderer {
  381. display: block;
  382. }
  383. .channelSearch ytd-browse[page-subtype=channels] ytd-two-column-browse-results-renderer {
  384. width: calc(100% - 32px) !important;
  385. max-width: calc(var(--videos-per-row) * (var(--ytd-rich-grid-item-max-width) + var(--ytd-rich-grid-item-margin))) !important;
  386. }
  387. .channelSearch #contents.ytd-item-section-renderer,
  388. .channelSearch ytd-item-section-renderer.ytd-section-list-renderer {
  389. display: contents;
  390. }
  391. .channelSearch #contents.ytd-section-list-renderer {
  392. display: flex;
  393. flex-wrap: wrap;
  394. }
  395. .channelSearch ytd-video-renderer,
  396. .channelSearch ytd-playlist-renderer,
  397. .channelSearch ytd-show-renderer {
  398. width: calc(100% / var(--videos-per-row) - var(--ytd-rich-grid-item-margin) - 0.01px);
  399. margin-left: calc(var(--ytd-rich-grid-item-margin) / 2);
  400. margin-right: calc(var(--ytd-rich-grid-item-margin) / 2);
  401. margin-bottom: 24px;
  402. }
  403. .channelSearch ytd-thumbnail.ytd-video-renderer,
  404. .channelSearch ytd-playlist-thumbnail.ytd-playlist-renderer,
  405. .channelSearch ytd-playlist-thumbnail.ytd-show-renderer {
  406. width: 100% !important;
  407. height: 100% !important;
  408. flex: 0 !important;
  409. }
  410. .channelSearch ytd-thumbnail.ytd-video-renderer:before,
  411. .channelSearch ytd-playlist-thumbnail.ytd-playlist-renderer:before,
  412. .channelSearch ytd-playlist-thumbnail.ytd-show-renderer:before {
  413. display: block;
  414. content: "";
  415. padding-top: 56.11%;
  416. }
  417. .channelSearch #dismissible.ytd-video-renderer,
  418. .channelSearch ytd-playlist-renderer,
  419. .channelSearch ytd-show-renderer {
  420. flex-direction: column;
  421. }
  422. .channelSearch #video-title {
  423. font-size: 1.6rem !important;
  424. line-height: 2.2rem !important;
  425. font-weight: 500 !important;
  426. }
  427. .channelSearch ytd-video-meta-block:not([rich-meta]) .ytd-video-meta-block:is(#byline-container,
  428. .channelSearch #metadata-line) {
  429. font-size: 1.4rem;
  430. line-height: 2rem;
  431. max-height: 2rem;
  432. }
  433. .channelSearch .title-and-badge.ytd-video-renderer,
  434. .channelSearch h3:is(.ytd-playlist-renderer, .ytd-show-renderer) {
  435. margin: 12px 0 4px 0;
  436. }
  437. .channelSearch #badges.ytd-video-renderer {
  438. margin: 4px 0 0 0;
  439. }
  440. .channelSearch #content.ytd-playlist-renderer {
  441. flex-basis: 100%;
  442. }
  443. .channelSearch .text-wrapper.ytd-video-renderer {
  444. max-width: 100%;
  445. }
  446. .channelSearch body[dir="ltr"] ytd-menu-renderer.ytd-video-renderer {
  447. position: absolute;
  448. right: -12px;
  449. margin-top: 4px;
  450. }
  451. .channelSearch body[dir="ltr"] #meta.ytd-video-renderer {
  452. padding-right: 24px;
  453. }
  454. .channelSearch body[dir="rtl"] ytd-menu-renderer.ytd-video-renderer {
  455. position: absolute;
  456. left: -12px;
  457. margin-top: 4px;
  458. }
  459. .channelSearch body[dir="rtl"] #meta.ytd-video-renderer {
  460. padding-left: 24px;
  461. }
  462. `;
  463.  
  464. document.addEventListener('yt-navigate-finish', function() {
  465. if (/@.*search/.test(window.location.href)) document.documentElement.classList.add('channelSearch');
  466. else document.documentElement.classList.remove('channelSearch');
  467. });