YouTube View Most Popular and Newest Uploader Videos (2018+)

See the user's most 'Popular' and 'Newest' video pages in a sliding-dropdown preview without even having to leave the video page.

  1. // ==UserScript==
  2. // @name YouTube View Most Popular and Newest Uploader Videos (2018+)
  3. // @namespace YVMUV
  4. // @version 23.1
  5. // @description See the user's most 'Popular' and 'Newest' video pages in a sliding-dropdown preview without even having to leave the video page.
  6. // @run-at document-start
  7. // @include *://www.youtube.com/watch?v=*
  8. // @include *://www.youtube.com/channel/*/videos?*
  9. // @exclude *://www.youtube.com/tv*
  10. // @exclude *://www.youtube.com/embed/*
  11. // @exclude *://www.youtube.com/live_chat*
  12. // @exclude *://www.youtube.com/feed/subscriptions?flowx=2*
  13. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
  14. // @require https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js
  15. // @resource primefix https://greasyfork.org/scripts/370052-youtube-old-site-design/code/Youtube%20Old%20Site%20Design.user.js
  16. // @resource primefixb https://greasyfork.org/scripts/32906-get-me-old-youtube/code/Get%20me%20Old%20Youtube.user.js
  17. // @resource spfremove https://greasyfork.org/scripts/16935-disable-spf-youtube/code/Disable%20SPF%20Youtube.user.js
  18. // @grant GM_getResourceText
  19. // @grant GM_getValue
  20. // @grant GM_setValue
  21. // @grant GM_addStyle
  22. // @author drhouse
  23. // @contributor Artain [Get me Old Youtube]
  24. // ==/UserScript==
  25. this.$ = this.jQuery = jQuery.noConflict(true);
  26.  
  27. $(document).ready(function () {
  28.  
  29. eval(GM_getResourceText("spfremove"));
  30. //eval(GM_getResourceText("primefix"));
  31. eval(GM_getResourceText("primefixb"));
  32.  
  33.  
  34. if(window.location != window.parent.location){
  35. $('#masthead-positioner').remove();
  36. $('div.branded-page-v2-top-row').remove();
  37. $('#appbar-guide-menu').remove();
  38. $('div#masthead-positioner-height-offset').remove();
  39.  
  40. var links = document.getElementById('content').getElementsByTagName('a');
  41.  
  42. for(var i=0 ; i<links.length ; i++){
  43. links[i].setAttribute('target', '_top');
  44. }
  45. }
  46. else {
  47. //not in frame
  48. }
  49.  
  50. var dest = '#watch7-user-header > div > a';
  51. var channel = $(dest).attr('href');
  52. var link = 'https://www.youtube.com' + channel + '/videos?view=0&sort=p&flow=grid';
  53.  
  54. var link2 = "'" + link + "'";
  55. var dest2 = $('#watch8-secondary-actions > div:nth-child(3)');
  56.  
  57. var linkdd = 'https://www.youtube.com' + channel + '/videos?view=0&sort=dd&flow=grid';
  58. var linkdd2 = "'" + linkdd + "'";
  59. $('<button class="yt-uix-button yt-uix-button-size-default yt-uix-button-has-icon yt-uix-tooltip addto-button" type="button" title="More actions" aria-pressed="false" id="popular" role="button" aria-haspopup="false" data-tooltip-text="Popular videos" aria-labelledby="yt-uix-tooltip93-arialabel"><span class="yt-uix-button-content"><a href="' + link + '">&nbsp;Most popular videos</a></span></button>').insertAfter(dest2).css('color', '#666')
  60. $('<button class="yt-uix-button yt-uix-button-size-default yt-uix-button-has-icon yt-uix-tooltip addto-button" type="button" title="More actions" aria-pressed="false" id="newest" role="button" aria-haspopup="false" data-tooltip-text="Newest videos" aria-labelledby="yt-uix-tooltip93-arialabel"><span class="yt-uix-button-content"><a href="' + linkdd + '">&nbsp;Newest videos</a></span></button>').insertAfter(dest2).css('color', '#666');
  61.  
  62. document.getElementById("popular").addEventListener("click", function(event){
  63. event.preventDefault()
  64. });
  65. document.getElementById("newest").addEventListener("click", function(event){
  66. event.preventDefault()
  67. });
  68.  
  69. $("head").append (
  70. '<link '
  71. + 'href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" '
  72. + 'rel="stylesheet" type="text/css">'
  73. );
  74.  
  75. $("head").append (
  76. '<link '
  77. + 'href="//unity.alwaysdata.net/test/push.css" '
  78. + 'rel="stylesheet" type="text/css">'
  79. );
  80.  
  81. +function ($) {
  82.  
  83. // PUSH PLUGIN CLASS DEFINITION
  84. // ============================
  85.  
  86. // variable used to indetify inilitizing of the Push plugin
  87. var pushAPI = '[data-toggle="push"]' // Default value is '[data-toggle="push"]'
  88.  
  89. // Main function to get off canvas element and options
  90. var Push = function (element, options) {
  91. this.element = element
  92. this.options = options
  93. }
  94.  
  95. // Current version
  96. Push.VERSION = '1.0'
  97.  
  98. // Transition duration
  99. Push.TRANSITION_DURATION = 150
  100.  
  101. // Default PUSH plugin settings
  102. Push.DEFAULTS = {
  103.  
  104. // Easing method, used for the element when it (opens / closes).
  105. easing : 'cubic-bezier(.2,.7,.5,1)', // Default value is 'cubic-bezier(.2,.7,.5,1)'
  106.  
  107. // Duration for an element to (open / close)
  108. duration : 1500, // Default value is 300
  109.  
  110. // Delay before the element (opens / closes)
  111. delay : 1000, // Default value is 0
  112.  
  113. // Distance an element (opens / closes)
  114. distance : 250, // Default value is 250
  115.  
  116. // Enable or disable Anti Scrolling (outside the element)
  117. antiScroll : false, // Default value is true
  118.  
  119. // Enable or disable keyboard closing (escape key to close the element)
  120. keyboard : true, // Default value is true
  121.  
  122. // Enable or disable a modal like overlay (outside the element).
  123. overlay : false, // Default value is true
  124.  
  125. // Canvas element (outside togglable sidebars).
  126. canvas : '#body-container' // Default value is '#wrapper'
  127. }
  128.  
  129. // Function to check if the canvas element is open
  130. Push.prototype.isOpen = function () {
  131.  
  132. // Return if the canvas element has the isOpen class
  133. return $(this.options.canvas).hasClass('isOpen')
  134. }
  135.  
  136. // Function to toggle (open or close)
  137. Push.prototype.toggle = function () {
  138.  
  139. // If canvas is already open
  140. if (this.isOpen()) {
  141. this.close() // close canvas and hide element
  142. }
  143.  
  144. // If canvas isn't open
  145. else {
  146. this.open() // open canvas and reveal element
  147. }
  148. }
  149.  
  150. // Function to find all fixed elements
  151. Push.prototype.findFixed = function () {
  152.  
  153. // Filter all elements with position: fixed
  154. var fixed_elements = $('*').filter(function() {
  155. return $(this).css("position") === 'fixed';
  156. }).not(this.element) // Skip sidebar element
  157.  
  158. // Return all fixed elements, except the sidebar element
  159. return fixed_elements
  160. }
  161.  
  162. // Function to disable scrolling outside an element
  163. Push.prototype.disableScrolling = function () {
  164.  
  165. // Add overflow hidden to body, to prevent scrolling
  166. $(document.body).css('overflow', 'hidden')
  167.  
  168. // On touch devices, overflow: hidden, is ignored. So we specefiy another prevention for touch devices.
  169. if ('ontouchstart' in document.documentElement) {
  170. $(document).on('touchmove.bs.push', function (e) {
  171. e.preventDefault()
  172. })
  173. }
  174. }
  175.  
  176. // Function to enable scrolling outside an element
  177. Push.prototype.enableScrolling = function () {
  178.  
  179. // Override the previously added overflow hiddien. To active normal scroll behaviour
  180. $(document.body).css('overflow', 'auto')
  181.  
  182. // Turn off the anti touch functionality for touch devices.
  183. if ('ontouchstart' in document.documentElement) {
  184. $(document).off('touchmove.bs.push')
  185. }
  186. }
  187.  
  188. // Function to disable key press to close an element
  189. Push.prototype.disableKeyboard = function () {
  190.  
  191. // Turn off the previously added keybind to close an open sidebar
  192. $(window).off('keydown.bs.push')
  193. }
  194.  
  195. // Function to enable key press to close an element
  196. Push.prototype.enableKeyboard = function () {
  197.  
  198. // Add functionality to close a sidebar, with a specefied keybind
  199. $(window).one('keydown.bs.push', $.proxy(function (e) {
  200. e.which == 13 && this.close() || e.which == 32 && this.close() // default value is: 27 (ESC key)
  201. }, this))
  202. }
  203.  
  204. // Function to remove an overlay outside the element
  205. Push.prototype.disableOverlay = function () {
  206.  
  207. // Prepare the overlay variable
  208. var $overlay = $(".modal-backdrop");
  209.  
  210. // Remove previously added overlay effect, from the canvas element
  211. $overlay.remove();
  212. }
  213.  
  214. // Function to add an overlay outside the element
  215. Push.prototype.enableOverlay = function () {
  216.  
  217. // Prepare the overlay variable
  218. var $overlay = $('<div class="modal-backdrop in"></div>');
  219.  
  220. // Add an overlay effect to the canvas element
  221. $overlay.appendTo(this.options.canvas);
  222. }
  223.  
  224. // Function to open an element
  225. Push.prototype.open = function () {
  226.  
  227. // Set the (that) variable, for easy access, and to avoid conflict.
  228. var that = this
  229.  
  230. // Get all fixed elements, except the sidebar elements
  231. var fixedElements = this.findFixed()
  232.  
  233. // If options is set to disable scrolling, disable it on opening
  234. if (this.options.antiScroll) this.disableScrolling()
  235.  
  236. // If options is set to enable keyboard, enable it on opening
  237. if (this.options.keyboard) this.enableKeyboard()
  238.  
  239. // If options is set to activate overlay, activate it on opening
  240. if (this.options.overlay) this.enableOverlay()
  241.  
  242. // Reveal the toggled sidebar
  243. $(this.element).removeClass('hidden')
  244.  
  245. // Open the canvas elemen
  246. $(this.options.canvas)
  247. .on('click.bs.push', $.proxy(this.close, this)) // If the user clicks on the canvas element, call the close functionality.
  248. .trigger('open.bs.push') // Trigger the open sequence
  249. .addClass('isOpen') // adds the isOpen class, to identify that the canvas is open
  250.  
  251. // If browser doesn't support CSS3 transitions & translations
  252. if (!$.support.transition) {
  253.  
  254. // Move all specefied fixed elements, when canvas is open
  255. fixedElements
  256. .css({
  257. 'left': this.options.distance + 'px',
  258. 'position': 'relative'
  259. })
  260.  
  261. // Move the actual canvas
  262. $(this.options.canvas)
  263. .css({
  264. 'left': this.options.distance + 'px',
  265. 'position': 'relative'
  266. })
  267. .trigger('opened.bs.push') // Indicate that the opening sequence is complete
  268. return
  269. }
  270.  
  271. // Prepare the CSS3 transitioning of the all fixed elements, except for the sidebars
  272. fixedElements
  273. .css({
  274. '-webkit-transition': '-webkit-transform ' + this.options.duration + 'ms ' + this.options.easing,
  275. '-ms-transition': '-ms-transform ' + this.options.duration + 'ms ' + this.options.easing,
  276. 'transition': 'transform ' + this.options.duration + 'ms ' + this.options.easing
  277. })
  278.  
  279. // Prepare the CSS3 transitioning of the canvas element
  280. $(this.options.canvas)
  281. .css({
  282. '-webkit-transition': '-webkit-transform ' + this.options.duration + 'ms ' + this.options.easing,
  283. '-ms-transition': '-ms-transform ' + this.options.duration + 'ms ' + this.options.easing,
  284. 'transition': 'transform ' + this.options.duration + 'ms ' + this.options.easing
  285. })
  286.  
  287. this.options.canvas.offsetWidth // Force reflow
  288.  
  289. // Move all specefied fixed elements, when the canvas opening sequence is initilised
  290. fixedElements
  291. .css({
  292. '-webkit-transform': 'translateY(' + this.options.distance + 'px)',
  293. '-ms-transform': 'translateY(' + this.options.distance + 'px)',
  294. 'transform': 'translateY(' + this.options.distance + 'px)'
  295. })
  296.  
  297. // Move the actual canvas element, when the opening sequence is initialised
  298. $(this.options.canvas)
  299. .css({
  300. '-webkit-transform': 'translateY(' + this.options.distance + 'px)',
  301. '-ms-transform': 'translateY(' + this.options.distance + 'px)',
  302. 'transform': 'translateY(' + this.options.distance + 'px)'
  303. })
  304. .one('bsTransitionEnd', function () {
  305. $(that.options.canvas).trigger('opened.bs.push') // Indicate that the opening sequence is complete
  306. })
  307. .emulateTransitionEnd(this.options.duration) // Emulate the ending prosedure of the canvas opening
  308. }
  309.  
  310. // Function to close an element
  311. Push.prototype.close = function () {
  312.  
  313. // Set the (that) variable, for easy access, and to avoid conflict.
  314. var that = this
  315.  
  316. // Get all fixed elements, except the sidebar elements
  317. var fixedElements = this.findFixed()
  318.  
  319. // If options is set to enable keyboard, disable it on closing
  320. if (this.options.keyboard) this.disableKeyboard()
  321.  
  322. // If options is set to activate overlay, deactivate it on closing
  323. if (this.options.overlay) this.disableOverlay()
  324.  
  325. // If options is set to disable scrolling, enable it on clsoing
  326. if (this.options.antiScroll) this.enableScrolling()
  327.  
  328. // Function to finilize the closing prosedure
  329. function complete () {
  330.  
  331. // Hide the toggled sidebar
  332. $(that.element).addClass('hidden')
  333.  
  334. // Reset the CSS3 transitioning and translation, of the all fixed elements back to default.
  335. fixedElements
  336. .css({
  337. '-webkit-transition': '',
  338. '-ms-transition': '',
  339. 'transition': '',
  340. '-webkit-transform': '',
  341. '-ms-transform': '',
  342. 'transform': ''
  343. })
  344.  
  345. // Reset the CSS3 transitioning and translation, of the canvas element back to default.
  346. $(that.options.canvas)
  347. .removeClass('isOpen') // remove the isOpen class, to identify that the canvas is closed
  348. .css({
  349. '-webkit-transition': '',
  350. '-ms-transition': '',
  351. 'transition': '',
  352. '-webkit-transform': '',
  353. '-ms-transform': '',
  354. 'transform': ''
  355. })
  356. .trigger('closed.bs.push') // Indicate that the closing sequence is complete
  357. }
  358.  
  359. // If browser doesn't support CSS3 transitions & translations
  360. if (!$.support.transition) {
  361.  
  362. // Move back all specefied fixed elements to default.
  363. fixedElements
  364. .css({
  365. 'left': '',
  366. 'position': ''
  367. })
  368.  
  369. // Move back the canvas element to default.
  370. $(this.options.canvas)
  371. .trigger('close.bs.push') // Trigger the close sequence
  372. .css({
  373. 'left': '',
  374. 'position': ''
  375. })
  376. .off('click.bs.push') // Turn off the click indicator for the canvas element
  377.  
  378. // Initilise the final closing functionality
  379. return complete()
  380. }
  381.  
  382. // Remove the CSS3 trasform values for all fixed elements
  383. fixedElements
  384. .css({
  385. '-webkit-transform': 'none',
  386. '-ms-transform': 'none',
  387. 'transform': 'none'
  388. })
  389.  
  390. // Remove the CSS3 transform values for the canvas element
  391. $(this.options.canvas)
  392. .trigger('close.bs.push') // Trigger the close sequence
  393. .off('click.bs.push') // Turn off the click indicator for the canvas element
  394. .css({
  395. '-webkit-transform': 'none',
  396. '-ms-transform': 'none',
  397. 'transform': 'none'
  398. })
  399. .one('bsTransitionEnd', complete) // // Initilize the complete function, to finilise the closing
  400. .emulateTransitionEnd(this.options.duration) // Emulate the ending prosedure of the canvas closing
  401. }
  402.  
  403. // PUSH PLUGIN DEFINITION
  404. // ======================
  405.  
  406. // Function to initlise the push Plugin
  407. function Plugin(option) {
  408.  
  409. // Begin initilising of the push plugin, for every indicator clicked
  410. return this.each(function () {
  411.  
  412. // Prepare a variable, containing the designated element
  413. var $this = $(this)
  414.  
  415. // Prepare a variable, containing the data-attributes
  416. var data = $this.data('bs.push')
  417.  
  418. // Prepare the plugin options
  419. var options = $.extend(
  420. {
  421. // extentions...
  422. },
  423. Push.DEFAULTS, // Initilise default plugin values
  424. $this.data(), // Get the extending options from the plugin indicator
  425. typeof option == 'object' && option // Setup an object with the designated options
  426. )
  427.  
  428. // If the push indicatore doesn't contain any data atributes. Use the default values
  429. if (!data) $this.data('bs.push', (data = new Push(this, options)))
  430.  
  431. // If the push indicator has a data attribute, containing a string
  432. if (typeof option == 'string') data[option]() // Setup the option
  433. })
  434. }
  435.  
  436. var old = $.fn.push
  437.  
  438. $.fn.push = Plugin
  439. $.fn.push.Constructor = Push
  440.  
  441. // PUSH AVOID CONFLICT
  442. // ====================
  443.  
  444. $.fn.push.noConflict = function () {
  445.  
  446. $.fn.push = old
  447. return this
  448. }
  449.  
  450.  
  451. // PUSH DATA-API
  452. // =============
  453.  
  454. // When clicked on a push data API indicator, initilise the plugin
  455. $(document).on('click', pushAPI, function () {
  456.  
  457. // Get all the data options
  458. var options = $(this).data()
  459.  
  460. // Get the designated data-target (sidebar element)
  461. var $target = $(this.getAttribute('data-target'))
  462.  
  463. // If no designated data-target is spcefied, use default value
  464. if (!$target.data('bs.push')) {
  465. $target.push(options) // Get all the other data options
  466. }
  467.  
  468. // Toggle the designated data-target (sidebar )
  469. $target.push('toggle')
  470. })
  471. }(jQuery);
  472.  
  473. //----------------------------------------------------------------
  474.  
  475. channel = $('#popular > span > a').attr('href');
  476. var channeln = $('#newest > span > a').attr('href');
  477.  
  478. var channel2 = channel + '#browse-items-primary';
  479. var channel2n = channeln + '#browse-items-primary';
  480.  
  481. var ifrm;
  482. ifrm = document.createElement("iframe");
  483. ifrm.setAttribute("src", channel2);
  484. ifrm.setAttribute("id", "ifrmz");
  485. ifrm.style.width = 1500+"px";
  486. ifrm.style.height = 548+"px";
  487.  
  488. var ifrm2;
  489. ifrm2 = document.createElement("iframe");
  490. ifrm2.setAttribute("src", channel2n);
  491. ifrm2.setAttribute("id", "ifrmz2");
  492. ifrm2.style.width = 1500+"px";
  493. ifrm2.style.height = 548+"px";
  494.  
  495. $('<nav class="push-sidebar hidden" id="sidebar-left"></nav>').insertBefore('#body-container');
  496. $('<nav class="push-sidebar hidden" id="sidebar-left2"></nav>').insertBefore('#body-container');
  497. $( "#body-container" ).wrap( '<section class="canvas" id="canvas"></section>' );
  498.  
  499. function newload(){
  500. $('nav#sidebar-left').append(ifrm);
  501. }
  502.  
  503. function newload2(){
  504. $('nav#sidebar-left2').append(ifrm2);
  505. }
  506.  
  507. $( "#newest" ).attr({
  508. 'class': "yt-uix-button yt-uix-button-size-default",
  509. 'data-toggle': "push",
  510. 'data-target': "#sidebar-left2",
  511. 'data-distance': "500"
  512. });
  513.  
  514. $( "#newest" ).click(function(e) {
  515. newload2();
  516.  
  517. });
  518.  
  519. $( "#popular" ).attr({
  520. 'class': "yt-uix-button yt-uix-button-size-default",
  521. 'data-toggle': "push",
  522. 'data-target': "#sidebar-left",
  523. 'data-distance': "500"
  524. });
  525.  
  526. $( "#popular" ).click(function(e) {
  527. newload();
  528. });
  529.  
  530. });