Youtube Sidebar Filter

Adds filter bars to YouTube's sidebar for Subscriptions and Playlists

  1. // ==UserScript==
  2. // @name Youtube Sidebar Filter
  3. // @homepageURL https://github.com/ZHAL9K/Youtube-Sidebar-Filter
  4. // @version 1.1
  5. // @description Adds filter bars to YouTube's sidebar for Subscriptions and Playlists
  6. // @author ZHAL9K
  7. // @match http://*.youtube.com/*
  8. // @match https://*.youtube.com/*
  9. // @exclude *://www.youtube.com/tv*
  10. // @exclude *://www.youtube.com/embed/*
  11. // @exclude *://www.youtube.com/live_chat*
  12. // @grant none
  13. // @run-at document-idle
  14. // @namespace https://greasyfork.org/users/106074
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. "use strict";
  19.  
  20. var subsSelectorId = "guide-channels";
  21. var subsFilterBarId = "zhal-subs-filter";
  22. var playlistsSelector = "#guide-container > div > ul > li:nth-child(2) > div > ul";
  23. var playlistsFilterBarId = "zhal-playlists-filter";
  24. var guideButtonId = "appbar-guide-button";
  25.  
  26. var subsFilterBar = null;
  27. var subsElements = [];
  28. var subsUL = document.getElementById(subsSelectorId);
  29.  
  30. var playlistsFilterBar = null;
  31. var playlistElements = [];
  32. var playlistsUL = document.querySelector(playlistsSelector);
  33.  
  34.  
  35. initSubsFilterBar();
  36. initPlaylistsFilterBar();
  37.  
  38. function initSubsFilterBar()
  39. {
  40. if (subsUL !== null)
  41. {
  42. subsFilterBar = createFilterBar(subsUL, subsFilterBarId, filterSubs);
  43. populateElements(subsElements, subsUL);
  44. }
  45. else
  46. {
  47. var guideButton = document.getElementById(guideButtonId);
  48. if (guideButton !== null)
  49. {
  50. guideButton.addEventListener("click", addSubsFilterBarOnGuideClick, false);
  51. }
  52. }
  53. }
  54.  
  55. function initPlaylistsFilterBar()
  56. {
  57. if (playlistsUL !== null)
  58. {
  59. playlistsFilterBar = createFilterBar(playlistsUL, playlistsFilterBarId, filterPlaylists);
  60. populateElements(playlistElements, playlistsUL);
  61. }
  62. else
  63. {
  64. var guideButton = document.getElementById(guideButtonId);
  65. if (guideButton !== null)
  66. {
  67. guideButton.addEventListener("click", addPlaylistsFilterBarOnGuideClick, false);
  68. }
  69. }
  70. }
  71.  
  72. function addSubsFilterBarOnGuideClick()
  73. {
  74. var timerFunc;
  75. if (subsFilterBar === null)
  76. {
  77. timerFunc = setInterval(myTimer, 1000);
  78. }
  79.  
  80. var count = 0;
  81.  
  82. function myTimer()
  83. {
  84. count++;
  85. subsUL = document.getElementById(subsSelectorId);
  86. if (subsFilterBar === null && subsUL !== null)
  87. {
  88. subsFilterBar = createFilterBar(subsUL, subsFilterBarId, filterSubs);
  89. populateElements(subsElements, subsUL);
  90. }
  91. if (count > 5 || subsFilterBar !== null)
  92. {
  93. clearInterval(timerFunc);
  94. }
  95. }
  96. }
  97.  
  98. function addPlaylistsFilterBarOnGuideClick()
  99. {
  100. var timerFunc;
  101. if (playlistsFilterBar === null)
  102. {
  103. timerFunc = setInterval(myTimer, 1000);
  104. }
  105.  
  106. var count = 0;
  107.  
  108. function myTimer()
  109. {
  110. count++;
  111. playlistsUL = document.querySelector(playlistsSelector);
  112. if (playlistsFilterBar === null && playlistsUL !== null)
  113. {
  114. playlistsFilterBar = createFilterBar(playlistsUL, playlistsFilterBarId, filterPlaylists);
  115. populateElements(playlistElements, playlistsUL);
  116. }
  117. if (count > 5 || playlistsFilterBar !== null)
  118. {
  119. clearInterval(timerFunc);
  120. }
  121. }
  122. }
  123.  
  124. function createFilterBar(listUL, id, listener)
  125. {
  126. var t = document.getElementById(id);
  127. if (t === null)
  128. {
  129. var parent = listUL.parentElement;
  130. var filterBar = document.createElement("input");
  131. filterBar.setAttribute("id", id);
  132. filterBar.setAttribute("class", "search-term");
  133. filterBar.setAttribute("style", "height: 20px");
  134. filterBar.setAttribute("placeholder", "Filter...");
  135. filterBar.addEventListener("keyup", listener, false);
  136. parent.insertBefore(filterBar, listUL);
  137. return filterBar;
  138. }
  139. else
  140. {
  141. console.log(id + " already created");
  142. return t;
  143. }
  144. }
  145.  
  146. function populateElements(elements, listUL)
  147. {
  148. var items = listUL.getElementsByClassName("guide-item");
  149. for (var ii = 0; ii < items.length; ii++)
  150. {
  151. var el = getAncestorLI(items[ii]);
  152. if (el !== null)
  153. {
  154. var name = items[ii].getAttribute("title").toUpperCase();
  155. var subtitle = "";
  156. var subtitles = items[ii].getElementsByClassName("guide-item-subtitle");
  157. if (subtitles.length > 0)
  158. {
  159. subtitle = subtitles[0].innerText.toUpperCase();
  160. }
  161. elements.push({ name: name, subtitle: subtitle, element: el });
  162. }
  163. }
  164. }
  165.  
  166. function filterSubs()
  167. {
  168. var filterBy = subsFilterBar.value.toUpperCase();
  169. filterElements(filterBy, subsElements);
  170. }
  171.  
  172. function filterPlaylists()
  173. {
  174. var filterBy = playlistsFilterBar.value.toUpperCase();
  175. filterElements(filterBy, playlistElements);
  176. }
  177.  
  178. function filterElements(filterBy, elements)
  179. {
  180. var temp, ii;
  181. for (ii = 0; ii < elements.length; ii++)
  182. {
  183. temp = elements[ii];
  184. if (temp.name.indexOf(filterBy) > -1 || (temp.subtitle.length > 0 && temp.subtitle.indexOf(filterBy) > -1))
  185. {
  186. if (temp.element.style.display !== "list-item")
  187. {
  188. temp.element.style.display = "list-item";
  189. }
  190. }
  191. else
  192. {
  193. if (temp.element.style.display !== "none")
  194. {
  195. temp.element.style.display = "none";
  196. }
  197. }
  198. }
  199. }
  200.  
  201. function getAncestorLI(el)
  202. {
  203. var retval = null;
  204. while (el)
  205. {
  206. if (el.tagName.indexOf("LI") > -1)
  207. {
  208. retval = el;
  209. break;
  210. }
  211. else if (el.tagName.indexOf("UL") > -1)
  212. {
  213. break;
  214. }
  215. el = el.parentElement;
  216. }
  217. return retval;
  218. }
  219. })();