DecentM / Old Youtube interface

// ==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);