Hide Watched & Selected Youtubes Videos

Hide viewed & selected videos from your subscriptions.

  1. // ==UserScript==
  2. // @name Hide Watched & Selected Youtubes Videos
  3. // @description Hide viewed & selected videos from your subscriptions.
  4. // @include https://www.youtube.com/feed/subscriptions*
  5. // @include https://www.youtube.com/feed/subscriptions*
  6. // @license MIT
  7. // @version 1.7
  8. // @date 31-01-2017
  9. // @require https://code.jquery.com/jquery-latest.min.js
  10. // @namespace https://greasyfork.org/users/59385
  11. // ==/UserScript==
  12. // js-cookie
  13. /*!
  14. * JavaScript Cookie v2.1.3
  15. * https://github.com/js-cookie/js-cookie
  16. *
  17. * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
  18. * Released under the MIT license
  19. */
  20. ;(function (factory) {
  21. var registeredInModuleLoader = false;
  22. if (typeof define === 'function' && define.amd) {
  23. define(factory);
  24. registeredInModuleLoader = true;
  25. }
  26. if (typeof exports === 'object') {
  27. module.exports = factory();
  28. registeredInModuleLoader = true;
  29. }
  30. if (!registeredInModuleLoader) {
  31. var OldCookies = window.Cookies;
  32. var api = window.Cookies = factory();
  33. api.noConflict = function () {
  34. window.Cookies = OldCookies;
  35. return api;
  36. };
  37. }
  38. }(function () {
  39. function extend () {
  40. var i = 0;
  41. var result = {};
  42. for (; i < arguments.length; i++) {
  43. var attributes = arguments[ i ];
  44. for (var key in attributes) {
  45. result[key] = attributes[key];
  46. }
  47. }
  48. return result;
  49. }
  50.  
  51. function init (converter) {
  52. function api (key, value, attributes) {
  53. var result;
  54. if (typeof document === 'undefined') {
  55. return;
  56. }
  57.  
  58. // Write
  59.  
  60. if (arguments.length > 1) {
  61. attributes = extend({
  62. path: '/'
  63. }, api.defaults, attributes);
  64.  
  65. if (typeof attributes.expires === 'number') {
  66. var expires = new Date();
  67. expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
  68. attributes.expires = expires;
  69. }
  70.  
  71. try {
  72. result = JSON.stringify(value);
  73. if (/^[\{\[]/.test(result)) {
  74. value = result;
  75. }
  76. } catch (e) {}
  77.  
  78. if (!converter.write) {
  79. value = encodeURIComponent(String(value))
  80. .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
  81. } else {
  82. value = converter.write(value, key);
  83. }
  84.  
  85. key = encodeURIComponent(String(key));
  86. key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
  87. key = key.replace(/[\(\)]/g, escape);
  88.  
  89. return (document.cookie = [
  90. key, '=', value,
  91. attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
  92. attributes.path ? '; path=' + attributes.path : '',
  93. attributes.domain ? '; domain=' + attributes.domain : '',
  94. attributes.secure ? '; secure' : ''
  95. ].join(''));
  96. }
  97.  
  98. // Read
  99.  
  100. if (!key) {
  101. result = {};
  102. }
  103.  
  104. // To prevent the for loop in the first place assign an empty array
  105. // in case there are no cookies at all. Also prevents odd result when
  106. // calling "get()"
  107. var cookies = document.cookie ? document.cookie.split('; ') : [];
  108. var rdecode = /(%[0-9A-Z]{2})+/g;
  109. var i = 0;
  110.  
  111. for (; i < cookies.length; i++) {
  112. var parts = cookies[i].split('=');
  113. var cookie = parts.slice(1).join('=');
  114.  
  115. if (cookie.charAt(0) === '"') {
  116. cookie = cookie.slice(1, -1);
  117. }
  118.  
  119. try {
  120. var name = parts[0].replace(rdecode, decodeURIComponent);
  121. cookie = converter.read ?
  122. converter.read(cookie, name) : converter(cookie, name) ||
  123. cookie.replace(rdecode, decodeURIComponent);
  124.  
  125. if (this.json) {
  126. try {
  127. cookie = JSON.parse(cookie);
  128. } catch (e) {}
  129. }
  130.  
  131. if (key === name) {
  132. result = cookie;
  133. break;
  134. }
  135.  
  136. if (!key) {
  137. result[name] = cookie;
  138. }
  139. } catch (e) {}
  140. }
  141.  
  142. return result;
  143. }
  144.  
  145. api.set = api;
  146. api.get = function (key) {
  147. return api.call(api, key);
  148. };
  149. api.getJSON = function () {
  150. return api.apply({
  151. json: true
  152. }, [].slice.call(arguments));
  153. };
  154. api.defaults = {};
  155.  
  156. api.remove = function (key, attributes) {
  157. api(key, '', extend(attributes, {
  158. expires: -1
  159. }));
  160. };
  161.  
  162. api.withConverter = init;
  163.  
  164. return api;
  165. }
  166.  
  167. return init(function () {});
  168. }));
  169. // Required
  170. var style = document.createElement('style');
  171. style.type = 'text/css';
  172. style.innerHTML = '.hideButton { width:30px; position: absolute; bottom: 0%; right: 2%; background-color: white;';
  173. style.innerHTML += 'border-radius: 50%; opacity: 1; }';
  174. style.innerHTML += '.hideButton:hover { opacity: 1; cursor: pointer;} ';
  175. //style.innerHTML += '.a.yt-uix-sessionlink.spf-link:hover .hideButton{ opacity: 1;}';
  176.  
  177. document.getElementsByTagName('head')[0].appendChild(style);
  178. // Start
  179.  
  180. function hideWatched() {
  181. if ($("#hide-videos").is(":checked") && window.location.href == "https://www.youtube.com/feed/subscriptions" || window.location.href == "http://www.youtube.com/feed/subscriptions") {
  182. $(".ytd-thumbnail-overlay-resume-playback-renderer").each(function() {
  183. $(this).closest("ytd-grid-video-renderer").hide();
  184. });
  185. }
  186. }
  187.  
  188. function showWatched() {
  189. $("ytd-grid-video-renderer").show("200");
  190. }
  191.  
  192. function refreshHideYoutubeVideos(showAll) {
  193. $('ytd-grid-video-renderer #dismissable #details').each(function() {
  194. if(!$(this).find('.hideButton').length) {
  195. $(this).append('<img src="https://image.flaticon.com/icons/svg/61/61685.svg" class="hideButton" />');
  196. }
  197. });
  198. if (Cookies.getJSON('hideYoutubeVideos') !== undefined && window.location.href == "https://www.youtube.com/feed/subscriptions" || window.location.href == "http://www.youtube.com/feed/subscriptions") {
  199. var data = Cookies.getJSON('hideYoutubeVideos').data;
  200. data.items.forEach(function(item) {
  201. //console.log(item.href);
  202. if(showAll === true) {
  203. $('a[href="' + item.href + '"]').each(function() {
  204. $(this).closest("ytd-grid-video-renderer").show("200");
  205. });
  206. } else if ($("#hide-videos").prop('checked') === true) {
  207. $('a[href="' + item.href + '"]').each(function() {
  208. $(this).closest("ytd-grid-video-renderer").hide();
  209. });
  210. } else {
  211. $('a[href="' + item.href + '"]').each(function() {
  212. $(this).closest("ytd-grid-video-renderer").show("200");
  213. });
  214. }
  215. });
  216. }
  217. }
  218.  
  219. $(function() {
  220. //Add mutation observer, checks for changes in DOM
  221. if (MutationObserver) {
  222. var myObserver = new MutationObserver(hideWatched);
  223. } else {
  224. var myObserver = new WebKitMutationObserver(hideWatched);
  225. }
  226. myObserver.observe(document, {
  227. childList: true,
  228. subtree: true
  229. });
  230. //Add mutation observer 2, checks for changes in DOM
  231. if (MutationObserver) {
  232. var myObserver2 = new MutationObserver(refreshHideYoutubeVideos);
  233. } else {
  234. var myObserver2 = new WebKitMutationObserver(refreshHideYoutubeVideos);
  235. }
  236. myObserver2.observe(document, {
  237. childList: true,
  238. subtree: true
  239. });
  240. // Add checkbox
  241. var checker = '<label id="checker-container" id="null">' +
  242. '<input type="checkbox" id="hide-videos" checked="" id="null"/>' +
  243. 'Hide watched & selected videos' +
  244. '</label>' ;
  245. $("#end").prepend(checker);
  246. $("#checker-container").css({
  247. 'color': "#666",
  248. "vertical-align": "middle",
  249. "text-align": "center"
  250. });
  251.  
  252.  
  253. var removeCookie = '<li><img id="removeCookie" src="https://www.iconsdb.com/icons/preview/gray/delete-xxl.png" width="16" style="vertical-align: middle; cursor: pointer;"</li>';
  254. $("#appbar-nav .appbar-nav-menu").append(removeCookie);
  255. $('#removeCookie').on('click', function(){
  256. setTimeout(function() {
  257. refreshHideYoutubeVideos(true);
  258. Cookies.remove('hideYoutubeVideos');
  259. }, 1000);
  260. });
  261.  
  262. //checkbox event
  263. $("#hide-videos").click(function() {
  264. refreshHideYoutubeVideos();
  265. if ($(this).is(":not(:checked)")) {
  266. showWatched();
  267. } else {
  268. hideWatched();
  269. }
  270. });
  271. //BONUS: always enable load more button.
  272. $("button.load-more-button").removeProp("disabled");
  273. hideWatched();
  274. //$(".yt-thumb").prepend('<img src="https://image.flaticon.com/icons/svg/61/61685.svg" class="hideButton" />');
  275. refreshHideYoutubeVideos();
  276. });
  277. // on click and Functions
  278. $('body').on('click', '.hideButton', function(e) {
  279. e.preventDefault();
  280. if (Cookies.getJSON('hideYoutubeVideos') !== undefined) {
  281. var data = Cookies.getJSON('hideYoutubeVideos').data;
  282. } else {
  283. var data = {
  284. items: []
  285. };
  286. }
  287. data.items.push({
  288. href: $(this).parent().parent().find('a').attr('href')
  289. });
  290. Cookies.set('hideYoutubeVideos', {
  291. data: data,
  292. }, {
  293. expires: 36500
  294. });
  295. refreshHideYoutubeVideos();
  296. setTimeout(function(){ window.history.back(); }, 250);
  297. });