YouTube Playlist Search Bar

Adds a search bar to YouTube playlists. Does NOT work with shorts or when playlist video filter is set to "Shorts".

  1. // ==UserScript==
  2. // @name YouTube Playlist Search Bar
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Adds a search bar to YouTube playlists. Does NOT work with shorts or when playlist video filter is set to "Shorts".
  6. // @match https://www.youtube.com/playlist*
  7. // @author Setnour6
  8. // @grant none
  9. // @license GPL-3.0
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. function createSearchBar() {
  16. // Check if custom search bar already exists
  17. if (document.getElementById('playlist-search-bar')) return;
  18.  
  19. // Find target element to place search bar under sorting options (works best)
  20. const target = document.querySelector('#page-manager ytd-playlist-video-list-renderer');
  21.  
  22. // Only proceed if target element exists
  23. if (!target) return;
  24.  
  25. const container = document.createElement('div');
  26. container.id = 'playlist-search-bar';
  27. container.style.display = 'flex';
  28. container.style.alignItems = 'center';
  29. container.style.marginBottom = '12px';
  30. container.style.padding = '6px 12px';
  31. container.style.borderRadius = '4px';
  32. container.style.border = '1px solid var(--yt-border-color)';
  33. container.style.backgroundColor = 'var(--yt-spec-general-background-a)';
  34.  
  35. container.style.width = '93%';
  36. container.style.marginLeft = 'auto';
  37. container.style.marginRight = 'auto';
  38.  
  39. const input = document.createElement('input');
  40. input.id = 'playlist-search-input';
  41. input.placeholder = 'Filter videos by title...';
  42. input.style.flex = '1';
  43. input.style.padding = '10px 12px';
  44. input.style.marginRight = '0';
  45. input.style.border = '1px solid var(--yt-border-color)';
  46. input.style.borderRadius = '20px 0 0 20px';
  47. input.style.color = 'var(--yt-spec-text-primary)';
  48. input.style.backgroundColor = 'var(--yt-spec-badge-chip-background)';
  49. input.style.fontFamily = 'Roboto, Noto, sans-serif';
  50. input.style.fontSize = '14px';
  51.  
  52. input.addEventListener('keydown', (event) => {
  53. if (event.key === 'Enter') {
  54. button.click();
  55. }
  56. });
  57.  
  58. const button = document.createElement('button');
  59. button.textContent = 'Search';
  60. button.style.padding = '10px 16px';
  61. button.style.border = 'none';
  62. button.style.borderRadius = '0 20px 20px 0';
  63. button.style.backgroundColor = '#FF0000';
  64. button.style.color = '#fff';
  65. button.style.cursor = 'pointer';
  66. button.style.fontFamily = 'Roboto, Noto, sans-serif';
  67. button.style.fontSize = '14px';
  68.  
  69. button.addEventListener('click', () => {
  70. const query = input.value.toLowerCase();
  71. if (query) {
  72. filterVideos(query);
  73. } else {
  74. resetFilter();
  75. }
  76. });
  77.  
  78. container.appendChild(input);
  79. container.appendChild(button);
  80.  
  81. target.parentNode.insertBefore(container, target);
  82. }
  83.  
  84. function filterVideos(query) {
  85. const videos = document.querySelectorAll('#contents ytd-playlist-video-renderer');
  86.  
  87. videos.forEach(video => {
  88. const title = video.querySelector('#video-title').textContent.toLowerCase();
  89.  
  90. const matches = title.includes(query);
  91. video.style.display = matches ? 'flex' : 'none';
  92. });
  93. }
  94.  
  95. function resetFilter() {
  96. const videos = document.querySelectorAll('#contents ytd-playlist-video-renderer');
  97. videos.forEach(video => {
  98. video.style.display = 'flex';
  99. });
  100. }
  101.  
  102. const observer = new MutationObserver(() => {
  103. createSearchBar();
  104. });
  105. observer.observe(document.body, { childList: true, subtree: true });
  106.  
  107. createSearchBar();
  108. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址