Raw Source
alike03 / YouTube Docking

// ==UserScript==
// @name        YouTube Docking
// @description Read the comments while watching the video
// @author      alike03
// @version     1.1.0
// @namespace   youtubeDOCK
// @icon        https://cdn3.iconfinder.com/data/icons/free-social-icons/67/youtube_circle_color-128.png
// @supportURL  https://github.com/alike03/Userscripts/issues
// @downloadURL https://raw.githubusercontent.com/alike03/Userscripts/master/src/YouTubeDocking.user.js
// @updateURL   https://raw.githubusercontent.com/alike03/Userscripts/master/meta/YouTubeDocking.user.js
// @homepageURL http://alike.ml/UserScript.php
// @match       https://*.youtube.com/*
// @require     https://code.jquery.com/jquery-3.4.1.min.js
// @copyright   2019, alike03 (https://openuserjs.org/users/alike03)
// @license     MIT
// ==/UserScript==

//window.addEventListener("yt-navigate-start", remove); // new youtube design
window.addEventListener("yt-navigate-finish", start); // new youtube design
window.addEventListener("load", start); // one-time early processing
//window.addEventListener("unload", saveData);

let miniplayer = null;
let miniplayerStatus = false;
let miniplayerEnable = false;
let miniplayerBlock = false;
let fullscreen = false;

function start() {
  if (window.location.href.indexOf('youtube.com/watch?v=') > -1) {
    let targetNode = $('#movie_player');
    observer.observe(targetNode[0], config);
    window.addEventListener('resize', fixVidSize);
    window.addEventListener("scroll", scrolling);
  }
  else {
    miniplayerEnable === false;
    //miniplayerStatus = false;
    disableMiniplayer();
    observer.disconnect();
    window.removeEventListener('resize', fixVidSize);
    window.removeEventListener("scroll", scrolling);
  }
}

function scrolling() {
  if (miniplayerBlock === false) {
    let limiter = $("#columns #alerts");
    let top_of_element = $(limiter).offset().top;
    let bottom_of_element = $(limiter).offset().top + $(limiter).outerHeight();
    let bottom_of_screen = $(window).scrollTop() + $(window).innerHeight();
    let top_of_screen = $(window).scrollTop();

    if ((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
      miniplayerEnable = false;
    }
    else {
      miniplayerEnable = true;
    }
    check();
  }
}

function check() {
  if (miniplayerEnable === true && miniplayerStatus === false && miniplayerBlock === false) {
    miniplayerStatus = true;
    enableMiniplayer();
    movePlayer();
  }
  if (miniplayerBlock === true || (miniplayerEnable === false && miniplayerStatus === true)) {
    miniplayerStatus = false;
    disableMiniplayer();
  }
}

function enableMiniplayer() {
  if (miniplayer === null) {
    let checkExist = setInterval(function () {
      if ($("#primary #primary-inner").length) {
        $("ytd-miniplayer").attr("enabled", "alike");
        $("ytd-miniplayer").attr("active", "alike");
        $("ytd-miniplayer").css("height", "225px");
        $("ytd-miniplayer").css("bottom", "310px");
        $("ytd-miniplayer #card").css("height", "225px");
        clearInterval(checkExist);
      }
    }, 100);
  }
}

function movePlayer() {
  let checkExist = setInterval(function () {
    if ($("ytd-player").length) {
      clearInterval(checkExist);
      //move player
      $("ytd-player").appendTo("#card #player-container");
      //add right classes
      let attr = $("ytd-watch-flexy").attr("theater-requested_");
      if (typeof attr !== typeof undefined && attr !== false) {
        $("#movie_player video").css("top", "0");
      }

      $("#movie_player .ytp-chrome-bottom .ytp-progress-bar").on("mouseover", blockClick);
      $("#movie_player .ytp-chrome-bottom .ytp-progress-bar").on("mousedown", blockClick);
      $("#movie_player .ytp-chrome-bottom .ytp-scrubber-container").css("display", "none");
      $("#movie_player .ytp-chrome-bottom .ytp-size-button").css("display", "none");
      $("#movie_player").removeClass(".ytp-large-width-mode .ad-created");
      $("#movie_player").addClass(".ytp-menu-shown .ytp-player-minimized .ytp-small-mode paused-mode");
      fixVidSize();
    }
  }, 100);
}

function blockClick(event) {
  event.stopPropagation();
  event.preventDefault();
  event.stopImmediatePropagation();
  return false;
}

function disableMiniplayer() {
  //remove miniplayer
  $("ytd-miniplayer").removeAttr("enabled");
  $("ytd-miniplayer").removeAttr("active");
  $("ytd-miniplayer").removeAttr("style");
  $("ytd-miniplayer #card").removeAttr("style");
  //move player

  let attr = $("ytd-watch-flexy").attr("theater-requested_");
  //let attr2 = $("ytd-watch-flexy").attr("fullscreen");
  if (typeof attr !== typeof undefined && attr !== false && !$("#player-theater-container #player-container ytd-player").length) {
    $("ytd-player").appendTo("#player-theater-container #player-container");
  }
  else {
    $("ytd-player").appendTo("#columns #player-container");
  }
  //add right classes
  $("#movie_player .ytp-chrome-bottom .ytp-progress-bar").off("mouseover", blockClick);
  $("#movie_player .ytp-chrome-bottom .ytp-progress-bar").off("mousedown", blockClick);
  $("#movie_player .ytp-chrome-bottom .ytp-scrubber-container").css("display", "");
  $("#movie_player .ytp-chrome-bottom .ytp-size-button").css("display", "");
  $("#movie_player").removeClass(".ytp-menu-shown .ytp-player-minimized .ytp-small-mode paused-mode");
  $("#movie_player").addClass(".ytp-large-width-mode .ad-created");
  fixVidSize();
}

function fixVidSize() {
  if (miniplayerStatus) {
    let sizeCheck = setInterval(function () {
      if (miniplayerStatus) {
        $("#movie_player video").css("width", "400px");
        $("#movie_player video").css("height", "225px");
        $("#movie_player video").css("left", "0");
        $("#movie_player .ytp-chrome-bottom").css("width", "376px");
      }
    }, 250);
    setTimeout(function () {
      clearInterval(sizeCheck);
    }, 5000);
  }
  else {
    $("#movie_player video").css("width", $("#movie_player").width());
    $("#movie_player video").css("height", $("#movie_player").height());
    $("#movie_player video").css("left", "0");
    let spacing = 24;
    if (fullscreen)
      spacing *= 2;
    $("#movie_player .ytp-chrome-bottom").css("width", $("#movie_player").width() - spacing);
  }
}

// Options for the observer (which mutations to observe)
const config = {
  attributes: true,
  childList: false,
  subtree: false,
  attributeFilter: ['class']
};

// Callback function to execute when mutations are observed
const callback = function (mutationsList, observer) {
  for (let mutation of mutationsList) {
    if (mutation.attributeName === "class") {
      var classList = mutation.target.className;
      // Do something here with class you're expecting
      if (classList.includes("ended-mode") || classList.includes("ytp-fullscreen")) {
        miniplayerBlock = true;
        miniplayerEnable = false;
        fullscreen = true;
        check();
      }
      else if (!classList.includes("ytp-fullscreen") && !classList.includes("ended-mode")) {
        miniplayerBlock = false;
        fullscreen = false;
        check();
      }
    }
  }
};

//document.addEventListener("fullscreenchange", function() {
//  if (document.fullscreenElement) 
//}, false);

// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);

console.log("Youtube Docking");