NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Old Youtube interface // @namespace http://tampermonkey.net/ // @version 1.0 // @description Forces the Youtube UI to use the old interface (which is secretly still available) // @author DecentM // @match *://www.youtube.com/* // @grant none // @require https://cdnjs.cloudflare.com/ajax/libs/qs/6.5.1/qs.min.js // @license MIT // ==/UserScript== // ======= * THIS SCRIPT IS INCOMPLETE * ======= // ======= * Right now, there is a flash of the new layout on every load. * ======= (function (window, document, undefined) { 'use strict'; var queryStringX = /[(\?|\&)]([^=]+)\=([^&#]+)/g; var disablePolymerOnURL = function disablePolymerOnURL(url) { return new Promise(function (resolve, reject) { try { var alreadyDisabled = !!url.match(/disable_polymer=true/g); if (!alreadyDisabled) { var qStringsMatch = url.match(queryStringX); var qStrings = ''; if (qStringsMatch) { qStrings = qStringsMatch.join(''); } var qStringsObj = Qs.parse(qStrings.replace('?', '')); qStringsObj.disable_polymer = true; resolve('?' + Qs.stringify(qStringsObj)); } else { resolve(); } } catch (error) { console.error(error); reject(error); } }); }; var transformLinks = function transformLinks(links) { return new Promise(function (resolve, reject) { try { links.forEach(function ($link) { var isEligible = !!$link.href.match(/^(?!http)|https\:\/\/www\.youtube\.com/g); if (isEligible) { disablePolymerOnURL($link.href).then(function (result) { $link.href = result; }); } }); } catch (error) { reject(error); } }); }; var processMutations = function processMutations(mutations) { return new Promise(function (resolve, reject) { try { var links = []; mutations.forEach(function (mutation) { var isLink = mutation.target.localName === 'a'; var hasHref = !!mutation.target.href; if (isLink && hasHref) { links.push(mutation.target); } }); transformLinks(links); resolve(); } catch (error) { reject(error); } }); }; var attachObserver = function attachObserver(selector) { return new Promise(function (resolve, reject) { try { console.log('Attaching observer to ' + selector); var observerTarget = document.querySelector(selector); var observerOptions = { 'characterData': true, 'subtree': true, 'childList': true }; var observer = new MutationObserver(processMutations); observer.observe(observerTarget, observerOptions); resolve(observer); } catch (error) { reject(error); } }); }; var disconnectObserver = function disconnectObserver(observer) { console.log('Disconnecting observer'); observer.disconnect(); }; var transformInitialLinks = function transformInitialLinks() { return new Promise(function (resolve, reject) { try { var links = []; var linkElements = document.querySelectorAll('a'); linkElements.forEach(function ($link) { var hasHref = !!$link.href; if (hasHref) { links.push($link); } }); transformLinks(links); } catch (error) { reject(error); } }); }; var main = function main() { console.log('Main'); transformInitialLinks().catch(function (error) { console.error(error); }); attachObserver('ytd-app').then(function (observer) { console.log('Observer running'); document.addEventListener('yt-navigate-start', function () { disconnectObserver(observer); }); }).catch(function (error) { console.error(error); }); }; var disablePolymerOnPage = function disablePolymerOnPage() { disablePolymerOnURL(location.href).then(function (result) { location.href = result; }); }; var pagePolymerDisabled = !!location.href.match(/disable_polymer=true/g); document.addEventListener('yt-navigate-finish', main); window.addEventListener('load', function () { console.log('Replacing links'); main(); }); if (!pagePolymerDisabled) { disablePolymerOnPage(); } })(window, window.document);