master 2ba94521d35f cached
9 files
125.7 KB
33.6k tokens
13 symbols
1 requests
Download .txt
Repository: Zren/ResizeYoutubePlayerToWindowSize
Branch: master
Commit: 2ba94521d35f
Files: 9
Total size: 125.7 KB

Directory structure:
gitextract_ufeouyam/

├── 153699.user.js
├── README.md
├── ResizeRedditToWindowSize.user.js
├── ResizeVideoDescription.md
├── ResizeVideoToWindowSize.user.js
├── YTDocs.md
├── changelog.md
├── description.md
└── ytwp.css

================================================
FILE CONTENTS
================================================

================================================
FILE: 153699.user.js
================================================
// ==UserScript==
// @name            Resize YT To Window Size
// @description     Moves the YouTube video to the top of the website and fill the window with the video player.
// @author          Chris H (Zren / Shade)
// @license         MIT
// @icon            https://s.ytimg.com/yts/img/favicon_32-vflOogEID.png
// @homepageURL     https://github.com/Zren/ResizeYoutubePlayerToWindowSize/
// @namespace       http://xshade.ca
// @version         139
// @include         http*://*.youtube.com/*
// @include         http*://youtube.com/*
// @include         http*://*.youtu.be/*
// @include         http*://youtu.be/*
// @grant           none
// ==/UserScript==

// Github:          https://github.com/Zren/ResizeYoutubePlayerToWindowSize
// GreasyFork:      https://greasyfork.org/scripts/811-resize-yt-to-window-size
// OpenUserJS.org:  https://openuserjs.org/scripts/zren/Resize_YT_To_Window_Size
// Userscripts.org: http://userscripts-mirror.org/scripts/show/153699

(function (window) {
    "use strict";

    //--- Settings
    var playerHeight = '100vh';
    var enableOnLoad = true;
    var scriptToggleKey = 'w';

    //--- Imported Globals
    // yt
    // ytcenter
    // html5Patched (Youtube+)
    // ytplayer
    var uw = window;

    //--- Already Loaded?
    // GreaseMonkey loads this script twice for some reason.
    if (uw.ytwp) return;

    //--- Is iframe?
    function inIframe () {
        try {
            return window.self !== window.top;
        } catch (e) {
            return true;
        }
    }
    if (inIframe()) return;

    //--- Utils
    function isStringType(obj) { return typeof obj === 'string'; }
    function isArrayType(obj) { return obj instanceof Array; }
    function isObjectType(obj) { return typeof obj === 'object'; }
    function isUndefined(obj) { return typeof obj === 'undefined'; }
    function buildVenderPropertyDict(propertyNames, value) {
        var d = {};
        for (var i in propertyNames)
            d[propertyNames[i]] = value;
        return d;
    }
    function observe(selector, config, callback) {
        var observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation){
                callback(mutation);
            });
        });
        var target = document.querySelector(selector);
        if (!target) {
            return null;
        }
        observer.observe(target, config);
        return observer;
    }

    //--- Stylesheet
    var JSStyleSheet = function(id) {
        this.id = id;
        this.stylesheet = '';
    };

    JSStyleSheet.prototype.buildRule = function(selector, styles) {
        var s = "";
        for (var key in styles) {
            s += "\t" + key + ": " + styles[key] + ";\n";
        }
        return selector + " {\n" + s + "}\n";
    };

    JSStyleSheet.prototype.appendRule = function(selector, k, v) {
        if (isArrayType(selector))
            selector = selector.join(',\n');
        var newStyle;
        if (!isUndefined(k) && !isUndefined(v) && isStringType(k)) { // v can be any type (as we stringify it).
            var d = {};
            d[k] = v;
            newStyle = this.buildRule(selector, d);
        } else if (!isUndefined(k) && isUndefined(v) && isObjectType(k)) {
            newStyle = this.buildRule(selector, k);
        } else {
            // Invalid Arguments
            console.log('Illegal arguments', arguments);
            return;
        }

        this.stylesheet += newStyle;
    };

    JSStyleSheet.injectIntoHeader = function(injectedStyleId, stylesheet) {
        var styleElement = document.getElementById(injectedStyleId);
        if (!styleElement) {
            styleElement = document.createElement('style');
            styleElement.type = 'text/css';
            styleElement.id = injectedStyleId;
            document.getElementsByTagName('head')[0].appendChild(styleElement);
        }
        styleElement.appendChild(document.createTextNode(stylesheet));
    };

    JSStyleSheet.prototype.injectIntoHeader = function() {
        JSStyleSheet.injectIntoHeader(this.id, this.stylesheet);
    };

    //--- History
    var HistoryEvent = function() {}
    HistoryEvent.listeners = []

    HistoryEvent.dispatch = function(state, title, url) {
      var stack = this.listeners
      for (var i = 0, l = stack.length; i < l; i++) {
        stack[i].call(this, state, title, url)
      }
    }
    HistoryEvent.onPushState = function(state, title, url) {
        HistoryEvent.dispatch(state, title, url)
        return HistoryEvent.origPushState.apply(window.history, arguments)
    }
    HistoryEvent.onReplaceState = function(state, title, url) {
        HistoryEvent.dispatch(state, title, url)
        return HistoryEvent.origReplaceState.apply(window.history, arguments)
    }
    HistoryEvent.inject = function() {
        if (!HistoryEvent.injected) {
            HistoryEvent.origPushState = window.history.pushState
            HistoryEvent.origReplaceState = window.history.replaceState

            window.history.pushState = HistoryEvent.onPushState
            window.history.replaceState = HistoryEvent.onReplaceState
            HistoryEvent.injected = true
        }
    }

    HistoryEvent.timerId = 0
    HistoryEvent.onTick = function() {
        var currentPage = window.location.pathname + window.location.search
        if (HistoryEvent.lastPage != currentPage) {
            HistoryEvent.dispatch({}, document.title, window.location.href)
            HistoryEvent.lastPage = currentPage
        }
    }
    HistoryEvent.startTimer = function() {
        HistoryEvent.lastPage = window.location.pathname + window.location.search
        HistoryEvent.timerId = setInterval(HistoryEvent.onTick, 500)
    }
    HistoryEvent.stopTimer = function() {
        clearInterval(HistoryEvent.timerId)
    }
    window.ytwpHistoryEvent = HistoryEvent


    //--- Constants
    var scriptShortName = 'ytwp'; // YT Window Player
    var scriptStyleId = scriptShortName + '-style'; // ytwp-style
    var scriptBodyClassId = scriptShortName + '-window-player'; // .ytwp-window-player
    var viewingVideoClassId = scriptShortName + '-viewing-video'; // .ytwp-viewing-video
    var topOfPageClassId = scriptShortName + '-scrolltop'; // .ytwp-scrolltop

    var scriptHtmlSelector = 'html:not([fullscreen="true"])';
    var scriptBodySelector = 'body.' + scriptBodyClassId; // body.ytwp-window-player
    scriptBodySelector += ':not(.enhancer-for-youtube-pinned-player)'; // Support "Enhancer for Youtube" (Pull Request #51)
    var scriptSelector = scriptHtmlSelector + ' ' + scriptBodySelector;

    var videoContainerId = 'player';
    var videoContainerPlacemarkerId = scriptShortName + '-placemarker'; // ytwp-placemarker

    var transitionProperties = ["transition", "-ms-transition", "-moz-transition", "-webkit-transition", "-o-transition"];
    var transformProperties = ["transform", "-ms-transform", "-moz-transform", "-webkit-transform", "-o-transform"];

    //--- YTWP
    var ytwp = uw.ytwp = {
        scriptShortName: scriptShortName, // YT Window Player
        log_: function(logger, args) { logger.apply(console, ['[' + this.scriptShortName + '] '].concat(Array.prototype.slice.call(args))); return 1; },
        log: function() { return this.log_(console.log, arguments); },
        error: function() { return this.log_(console.error, arguments); },

        initialized: false,
        pageReady: false,
        isWatchPage: false,
    };

    ytwp.debugPage = function() {
        function prettyHtml(el) {
            var s = el.outerHTML
            return s.substr(0, s.indexOf('>')+1)
        }
        var defStyle = {
            'display':'block', 'position': 'static',
            'left': 'auto', 'right': 'auto', 'top': 'auto', 'bottom': 'auto',
            'padding-left':'0px', 'padding-right':'0px', 'padding-top':'0px', 'padding-bottom':'0px',
            'margin-left':'0px', 'margin-right':'0px', 'margin-top':'0px', 'margin-bottom':'0px',
            'width': 'auto', 'min-width': 'auto', 'max-width': 'auto',
            'height': 'auto', 'min-height': 'auto', 'max-height': 'auto',
        }
        var keyFilter = Object.keys(defStyle)
        var node = document.querySelector('#movie_player video')
        var outStr = ''
        while (node && node.parentNode) {
            var style = getComputedStyle(node)
            var styleDiff = {}
            for (var key of style) {
                if (keyFilter.includes(key) && style[key] != defStyle[key]) {
                    styleDiff[key] = style[key]
                }
            }
            outStr += prettyHtml(node) + ' ' + JSON.stringify(styleDiff) + '\n'
            node = node.parentNode
        }
        outStr = outStr.split('\n').reverse().join('\n')
        ytwp.log('debugPage', outStr)
    }

    ytwp.hasYoutubeChanged = function() {
        var tree = [
            'html',
            'body',
            'ytd-app',
            '#content.ytd-app',
            'ytd-page-manager#page-manager.ytd-app',
            'ytd-watch-flexy.ytd-page-manager',
            '#full-bleed-container.ytd-watch-flexy',
            '#player-full-bleed-container.ytd-watch-flexy',
            '#player-container.ytd-watch-flexy',
            'ytd-player#ytd-player.ytd-watch-flexy',
            '#container.ytd-player',
            '.html5-video-player',
            '.html5-video-container',
            'video.html5-main-video',
        ]
        tree = tree.reverse()
        var node = document.querySelector(tree[0])
        if (!node) {
            ytwp.error('YT has changed!', tree[0], 'no longer exists!')
            return true
        }
        for (var i = 1; i < tree.length; i++) {
            var parent = node.parentNode
            var selector = tree[i]
            if (parent.matches(selector)) {
                node = parent
            } else {
                ytwp.error('YT has changed!', selector, 'no longer exists!')
            }
        }
        return false
    }

    ytwp.isWatchUrl = function (url) {
        if (!url)
            url = uw.location.href;
        if (url.match(/https?:\/\/(www\.)?youtube.com\/(c|channel|user)\/[^\/]+\/live/)) {
            if (document.querySelector('ytd-browse')) {
                return false
            } else {
                return true
            }
        }
        return url.match(/https?:\/\/(www\.)?youtube.com\/watch\?/);
    };

    ytwp.setTheaterMode = function(enable) {
        // ytwp.log('setTheaterMode', enable)

        var watchElement = document.querySelector('ytd-watch:not([hidden])') || document.querySelector('ytd-watch-flexy:not([hidden])') || document.querySelector('ytd-watch-grid:not([hidden])')
        if (watchElement) {
            var isTheater = watchElement.hasAttribute('theater')
            if (enable != isTheater) {
                // Note: (Issue #75) ytd-watch-flexy watchElement.querySelector() will find
                // Nothing for some reason. We need to query from the document scope.
                var sizeButton = document.querySelector(watchElement.tagName + ':not([hidden]) button.ytp-size-button')
                if (!sizeButton) {
                    var screenModeButtons = document.querySelectorAll(watchElement.tagName + ':not([hidden]) button.ytp-screen-mode-settings-button')
                    sizeButton = screenModeButtons[1] // 2nd button is "Theater mode (t)"
                }
                if (sizeButton) {
                    sizeButton.click()
                }
            }
            watchElement.canFitTheater_ = true // When it's too small, it disables the theater mode.
        } else if (watchElement = document.querySelector('#page.watch')) {
            var isTheater = watchElement.classList.contains('watch-stage-mode')
            if (enable != isTheater) {
                var sizeButton = watchElement.querySelector('button.ytp-size-button')
                if (sizeButton) {
                    sizeButton.click()
                }
            }
        }
    }
    ytwp.enterTheaterMode = function() {
        // ytwp.log('enterTheaterMode')
        if (!document.body.classList.contains(scriptBodyClassId)) {
            return
        }

        ytwp.setTheaterMode(true)
    }
    ytwp.enterTheaterMode();
    uw.addEventListener('resize', ytwp.enterTheaterMode);

    ytwp.detectPlayerUnavailable = function() {
        if (document.querySelector('[player-unavailable]')) {
            ytwp.event.removeBodyClass()
        }
    }


    ytwp.init = function() {
        ytwp.log('init');
        if (!ytwp.initialized) {
            ytwp.isWatchPage = ytwp.isWatchUrl();
            if (ytwp.isWatchPage) {
                ytwp.removeSearchAutofocus();
                if (!document.getElementById(scriptStyleId)) {
                    ytwp.event.initStyle();
                }
                ytwp.initScroller();
                ytwp.initialized = true;
                ytwp.pageReady = false;
            }
        }
        ytwp.event.onWatchInit();
        if (ytwp.isWatchPage) {
            ytwp.html5PlayerFix();
        }
    }

    ytwp.initScroller = function() {
        // Register listener & Call it now.
        uw.addEventListener('scroll', ytwp.onScroll, false);
        uw.addEventListener('resize', ytwp.onScroll, false);
        ytwp.onScroll();
    }

    ytwp.onScroll = function() {
        var viewportHeight = document.documentElement.clientHeight;

        // topOfPageClassId
        if (ytwp.isWatchPage && uw.scrollY == 0) {
            document.body.classList.add(topOfPageClassId);
            //var player = document.getElementById('movie_player');
            //if (player)
            //    player.focus();
        } else {
            document.body.classList.remove(topOfPageClassId);
        }

        // viewingVideoClassId
        if (ytwp.isWatchPage && uw.scrollY <= viewportHeight) {
            document.body.classList.add(viewingVideoClassId);
        } else {
            document.body.classList.remove(viewingVideoClassId);
        }
    }

    ytwp.event = {
        initStyle: function() {
            ytwp.log('initStyle');
            ytwp.style = new JSStyleSheet(scriptStyleId);
            ytwp.event.buildStylesheet();
            // Duplicate stylesheet targeting data-spf-name if enabled.
            if (uw.spf) {
                var temp = scriptBodySelector;
                scriptBodySelector = 'body[data-spf-name="watch"]';
                scriptSelector = scriptHtmlSelector + ' ' + scriptBodySelector
                ytwp.event.buildStylesheet();
                ytwp.style.appendRule('body[data-spf-name="watch"]:not(.ytwp-window-player) #masthead-positioner',  {
                    'position': 'absolute',
                    'top': playerHeight + ' !important'
                });
            }
            ytwp.style.injectIntoHeader();
        },
        buildStylesheet: function() {
            ytwp.log('buildStylesheet');
            //--- Browser Scrollbar
            // Chrome/Webkit
            ytwp.style.appendRule(scriptBodySelector + '::-webkit-scrollbar', {
                'width': '0 !important',
                'height': '0 !important',
            });
            // Firefox/Gecko
            // Requires about:config flag to be toggled as of FireFox v63
            // https://github.com/Zren/ResizeYoutubePlayerToWindowSize/issues/42
            ytwp.style.appendRule('html', {
                'scrollbar-width': 'none',
            });

            //--- Video Player
            var d;
            d = buildVenderPropertyDict(transitionProperties, 'left 0s linear, padding-left 0s linear');
            d['padding'] = '0 !important';
            d['margin'] = '0 !important';
            ytwp.style.appendRule([
                scriptBodySelector + ' #player',
                scriptBodySelector + '.ytcenter-site-center.ytcenter-non-resize.ytcenter-guide-visible #player',
                scriptBodySelector + '.ltr.ytcenter-site-center.ytcenter-non-resize.ytcenter-guide-visible.guide-collapsed #player',
                scriptBodySelector + '.ltr.ytcenter-site-center.ytcenter-non-resize.ytcenter-guide-visible.guide-collapsed #player-legacy',
                scriptBodySelector + '.ltr.ytcenter-site-center.ytcenter-non-resize.ytcenter-guide-visible.guide-collapsed #watch7-main-container',
            ], d);
            //
            d = buildVenderPropertyDict(transitionProperties, 'width 0s linear, left 0s linear');

            // Bugfix for Firefox
            // Parts of the header (search box) are hidden under the player.
            // Firefox doesn't seem to be using the fixed header+guide yet.
            d['float'] = 'initial';

            // Skinny mode
            d['left'] = 0;
            d['margin-left'] = 0;

            ytwp.style.appendRule(scriptBodySelector + ' #player-api', d);

            // Theater mode
            ytwp.style.appendRule(scriptBodySelector + ' .watch-stage-mode #player .player-api', {
                'left': 'initial !important',
                'margin-left': 'initial !important',
            });

            // Hide the cinema/wide mode button since it's useless.
            //ytwp.style.appendRule(scriptBodySelector + ' #movie_player .ytp-size-button', 'display', 'none');

            // !important is mainly for simplicity, but is needed to override the !important styling when the Guide is open due to:
            // .sidebar-collapsed #watch7-video, .sidebar-collapsed #watch7-main, .sidebar-collapsed .watch7-playlist { width: 945px!important; }
            // Also, Youtube Center resizes #player at element level.
            // Don't resize if Youtube+'s html.floater is detected.
            // Dont' resize if Youtube+ (Iridium/Material)'s html.iri-always-visible is detected.
            ytwp.style.appendRule(
                [
                    scriptSelector + ' #player',
                    scriptSelector + ' #player-wrap',
                    scriptSelector + ' #player-api',
                    scriptHtmlSelector + ':not(.floater):not(.iri-always-visible) ' + scriptBodySelector + ' #movie_player',
                    scriptSelector + ' #player-mole-container',
                    scriptHtmlSelector + ':not(.floater):not(.iri-always-visible) ' + scriptBodySelector + ' .html5-video-container',
                    scriptHtmlSelector + ':not(.floater):not(.iri-always-visible) ' + scriptBodySelector + ' .html5-main-video',
                    scriptSelector + ' ytd-watch-flexy[theater] #player-theater-container.ytd-watch-flexy',
                    scriptSelector + ' ytd-watch-flexy[flexy] #player-container-outer.ytd-watch-flexy',
                    scriptSelector + ' ytd-watch-flexy[flexy] #player-container-inner.ytd-watch-flexy',
                    scriptSelector + ' ytd-watch-flexy[flexy] #player-container.ytd-watch-flexy',
                    scriptSelector + ' ytd-watch-grid[theater] #player-theater-container.ytd-watch-grid',
                    scriptSelector + ' ytd-watch-grid[flexy] #player-container-outer.ytd-watch-grid',
                    scriptSelector + ' ytd-watch-grid[flexy] #player-container-inner.ytd-watch-grid',
                    scriptSelector + ' ytd-watch-grid[flexy] #player-container.ytd-watch-grid',
                ],
                {
                    'width': '100% !important',
                    'min-width': '100% !important',
                    'max-width': '100% !important',
                    'height': playerHeight + ' !important',
                    'min-height': playerHeight + ' !important',
                    'max-height': playerHeight + ' !important',
                }
            );

             ytwp.style.appendRule(
                [
                    scriptSelector + ' #player',
                    scriptSelector + ' .html5-main-video',
                ],
                {
                    'top': '0 !important',
                    'right': '0 !important',
                    'bottom': '0 !important',
                    'left': '0 !important',
                }
            );
            // Resize #player-unavailable, #player-api
            // Using min/max width/height will keep
            ytwp.style.appendRule(scriptSelector + ' #player .player-width', 'width', '100% !important');
            ytwp.style.appendRule(scriptSelector + ' #player .player-height', 'height', '100% !important');

            // Fix video overlays
            ytwp.style.appendRule([
                scriptSelector + ' .html5-video-player .ad-container-single-media-element-annotations', // Ad
                scriptSelector + ' .html5-video-player .ytp-upnext', // Autoplay Next Video
            ], 'top', '0');

            // Fix video cropping (object-fit: cover) (Issue #70)
            ytwp.style.appendRule(scriptSelector + ' .ytp-fit-cover-video .html5-main-video', 'object-fit', 'contain !important');
            // Thumbnail cropping
            ytwp.style.appendRule(scriptSelector + ' .ytp-cued-thumbnail-overlay-image', {
                'background-size': 'contain !important',
                '-moz-background-size': 'contain !important',
                '-webkit-background-size': 'contain !important',
            });

            //--- Video Container Background
            ytwp.style.appendRule(scriptSelector + ' #movie_player', 'background-color', '#000000');

            //--- Move Video Player
            ytwp.style.appendRule(scriptSelector + ' #player', {
                'position': 'absolute',
                // Already top:0; left: 0;
            });
            ytwp.style.appendRule(scriptSelector, { // body
                'margin-top': playerHeight,
            });

            // Fix the top right avatar button
            ytwp.style.appendRule(scriptSelector + ' button.ytp-button.ytp-cards-button', 'top', '0');


            //--- Sidebar
            // Remove the transition delay as you can see it moving on page load.
            d = buildVenderPropertyDict(transitionProperties, 'margin-top 0s linear, padding-top 0s linear');
            d['margin-top'] = '0 !important';
            d['top'] = '0 !important';
            ytwp.style.appendRule(scriptSelector + ' #watch7-sidebar', d);

            ytwp.style.appendRule(scriptSelector + '.cardified-page #watch7-sidebar-contents', 'padding-top', '0');

            //--- Absolutely position the fixed header.
            // Masthead
            ytwp.style.appendRule('#skip-navigation.ytd-masthead', 'top', '-150vh'); // Normally -1000px can be shorter than screen (Issue #77)
            d = buildVenderPropertyDict(transitionProperties, 'top 0s linear !important');
            ytwp.style.appendRule(scriptSelector + '.hide-header-transition #masthead-positioner', d);
            ytwp.style.appendRule(scriptSelector + '.' + viewingVideoClassId + ' #masthead-positioner', {
                'position': 'absolute',
                'top': playerHeight + ' !important'
            });
            // Lower masthead below Youtube+'s html.floater
            ytwp.style.appendRule('html.floater ' + scriptBodySelector + '.' + viewingVideoClassId + ' #masthead-positioner', {
                'z-index': '5',
            });
            // Autocomplete popup
            ytwp.style.appendRule(scriptSelector + ' .sbdd_a', {
                'top': '56px',
            });
            ytwp.style.appendRule(scriptSelector + '.' + viewingVideoClassId + ' .sbdd_a', {
                'top': 'calc(' + playerHeight + ' + 56px) !important',
                'position': 'absolute !important',
            });

            // Guide
            // When watching the video, we need to line it up with the masthead.
            ytwp.style.appendRule(scriptSelector + '.' + viewingVideoClassId + ' #appbar-guide-menu', {
                'display': 'initial',
                'position': 'absolute',
                'top': '100% !important' // Masthead height
            });
            ytwp.style.appendRule(scriptSelector + '.' + viewingVideoClassId + ' #page.watch #guide', {
                'display': 'initial',
                'margin': '0',
                'position': 'initial'
            });
            // When the guide is open, it adds body{top:-1000px} which messes with the top position (Issue #77)
            ytwp.style.appendRule(scriptSelector + '.lock-scrollbar', {
                'top': '0 !important',
                'position': 'static !important',
            });


            //---
            // MiniPlayer-Bar
            ytwp.style.appendRule(scriptSelector + ' #miniplayer-bar #player', {
                'position': 'static',
            });
            ytwp.style.appendRule(
                [
                    scriptSelector + ' #miniplayer-bar #player',
                    scriptSelector + ' #miniplayer-bar #player-api',
                    scriptHtmlSelector + ':not(.floater):not(.iri-always-visible) ' + scriptBodySelector + ' #miniplayer-bar #movie_player',
                    scriptSelector + ' #player-mole-container',
                    scriptHtmlSelector + ':not(.floater):not(.iri-always-visible) ' + scriptBodySelector + ' #miniplayer-bar .html5-video-container',
                    scriptHtmlSelector + ':not(.floater):not(.iri-always-visible) ' + scriptBodySelector + ' #miniplayer-bar .html5-main-video',
                ],
                {
                    'width': '252px !important',
                    'min-width': '252px !important',
                    'max-width': '252px !important',
                    'height': '142px !important',
                    'min-height': '142px !important',
                    'max-height': '142px !important',
                }
            );
            // Override inline style (caused by a JS animation) that breaks the miniplayer video
            // https://github.com/Zren/ResizeYoutubePlayerToWindowSize/issues/41#issuecomment-439710130
            ytwp.style.appendRule('.video-stream.html5-main-video', {
                'top': '0 !important',
            });

            //---
            // Hide Scrollbars
            ytwp.style.appendRule(scriptSelector + '.' + topOfPageClassId, 'overflow-x', 'hidden');


            //--- Fix Other Possible Style Issues
            ytwp.style.appendRule(scriptSelector + ' #placeholder-player', 'display', 'none');
            ytwp.style.appendRule(scriptSelector + ' #watch-sidebar-spacer', 'display', 'none');
            ytwp.style.appendRule(scriptSelector + ' .skip-nav', 'display', 'none');

            //--- Whitespace Leftover From Moving The Video
            ytwp.style.appendRule(scriptSelector + ' #page.watch', 'padding-top', '0');
            ytwp.style.appendRule(scriptSelector + ' .player-branded-banner', 'height', '0');

            //--- Youtube+ Compatiblity
            ytwp.style.appendRule(scriptSelector + ' #body-container', 'position', 'static');
            ytwp.style.appendRule(scriptHtmlSelector + '.part_static_size:not(.content-snap-width-skinny-mode) ' + scriptBodySelector + ' .watch-non-stage-mode #player-playlist', 'width', '1066px');

            //--- Playlist Bar
            ytwp.style.appendRule([
                scriptSelector + ' #placeholder-playlist',
                scriptSelector + ' #player .player-height#watch-appbar-playlist',
            ], {
                'height': '540px !important',
                'max-height': '540px !important',
            });

            d = buildVenderPropertyDict(transitionProperties, 'transform 0s linear');
            ytwp.style.appendRule(scriptSelector + ' #watch-appbar-playlist', d);
            d = buildVenderPropertyDict(transformProperties, 'translateY(0px)');
            d['margin-left'] = '0';
            d['top'] = 'calc(' + playerHeight + ' + 60px)';
            ytwp.style.appendRule(scriptSelector + ' #player .player-height#watch-appbar-playlist', d);
            ytwp.style.appendRule(scriptSelector + ' .playlist-videos-list', {
                'max-height': '470px !important',
                'height': 'initial !important',
            });

            // Old layout `&disable_polymer=true`
            ytwp.style.appendRule(scriptSelector + ' #player .player-height#watch-appbar-playlist', {
                'left': 'calc((100vw - 1066px)/2 + 640px + 10px)',
                'width': '416px',
            });
            ytwp.style.stylesheet += '@media screen and (min-height: 630px) and (min-width: 1294px) {\n';
            ytwp.style.appendRule(scriptSelector + ' #player .player-height#watch-appbar-playlist', {
                'left': 'calc((100vw - 1280px)/2 + 854px + 10px)',
            });
            ytwp.style.stylesheet += '}\n @media screen and (min-width: 1720px) and (min-height:980px) {\n';
            ytwp.style.appendRule(scriptSelector + ' #player .player-height#watch-appbar-playlist', {
                'left': 'calc((100vw - 1706px)/2 + 1280px + 10px)',
            });
            ytwp.style.stylesheet += '}\n';

            //---
            // Material UI
            ytwp.style.appendRule(scriptSelector + '.ytwp-scrolltop #extra-buttons', 'display', 'none !important');
            // ytwp.style.appendRule('body > #player:not(.ytd-watch)', 'display', 'none');
            // ytwp.style.appendRule('body.ytwp-viewing-video #content:not(app-header-layout) ytd-page-manager', 'margin-top', '0 !important');
            // ytwp.style.appendRule('.ytd-watch-0 #content-separator.ytd-watch', 'margin-top', '0');
            ytwp.style.appendRule('ytd-app', 'position', 'static !important');
            ytwp.style.appendRule('ytd-watch #top', 'margin-top', '71px !important'); // 56px (topnav height) + 15px (margin)
            ytwp.style.appendRule('ytd-watch #container', 'margin-top', '0 !important');
            ytwp.style.appendRule('ytd-watch #content-separator', 'margin-top', '0 !important');
            // Note: Container is now relative since 2023 June (Issue #77)
            // Note: Container is now a full-bleed-player (Issue #79)
            ytwp.style.appendRule([
                scriptSelector + ' ytd-watch-flexy[theater] #player-wide-container.ytd-watch-flexy',
                scriptSelector + ' ytd-watch-flexy[fullscreen] #player-wide-container.ytd-watch-flexy',
                scriptSelector + ' ytd-watch-flexy[full-bleed-player] #player-full-bleed-container.ytd-watch-flexy', // Issue #79 (2023-08-17)
                scriptSelector + ' ytd-watch-flexy[full-bleed-player] #full-bleed-container.ytd-watch-flexy', // Issue #79 (2023-08-22)
                scriptSelector + ' ytd-watch-grid[theater] #player-wide-container.ytd-watch-grid',
                scriptSelector + ' ytd-watch-grid[fullscreen] #player-wide-container.ytd-watch-grid',
                scriptSelector + ' ytd-watch-grid[full-bleed-player] #player-full-bleed-container.ytd-watch-grid', // Issue #81 (2023-08-30)
                scriptSelector + ' ytd-watch-grid[full-bleed-player] #full-bleed-container.ytd-watch-grid', // Issue #81 (2023-08-30)
            ], {
                'position': 'static',
                'height': 0,
                'min-height': 0,
            });

            ytwp.style.appendRule(scriptSelector + '.ytwp-viewing-video ytd-app #masthead-container.ytd-app', {
                'position': 'absolute',
                'top': playerHeight,
                'z-index': 0,
            });
            ytwp.style.appendRule(scriptSelector + '.ytwp-viewing-video ytd-watch #masthead-positioner', {
                'top': playerHeight + ' !important',
            });
            ytwp.style.appendRule(scriptSelector + ' .ytp-cued-thumbnail-overlay', 'z-index', '10');

            //---
            // Flexy UI
            ytwp.style.appendRule([
                scriptSelector + ' ytd-watch-flexy[theater] #player-theater-container.ytd-watch-flexy',
                scriptSelector + ' ytd-watch-grid[theater] #player-theater-container.ytd-watch-grid',
            ], {
                'position': 'absolute',
                'top': '0',
            });
            // Youtube seems to be ignoring the margin/padding top in certain elements for some reason (Issue #88)
            // ytwp.style.appendRule([
            //     scriptSelector + ' ytd-watch-flexy',
            //     scriptSelector + ' ytd-watch-grid',
            // ], 'padding-top', '71px'); // 56px (topnav height) + 15px (margin)
            ytwp.style.appendRule('#page-manager.ytd-app', 'padding-top', 'var(--ytd-masthead-height,var(--ytd-toolbar-height))');
            ytwp.style.appendRule(scriptSelector + ' #error-screen', 'z-index', '11');
        },
        onWatchInit: function() {
            ytwp.log('onWatchInit');
            if (!ytwp.initialized) return;
            if (ytwp.pageReady) return;

            if (enableOnLoad) {
                ytwp.event.addBodyClass();
            }
            if (ytwp.hasYoutubeChanged()) {
                ytwp.debugPage()
            }
            ytwp.pageReady = true;
        },
        onDispose: function() {
            ytwp.log('onDispose');
            ytwp.initialized = false;
            ytwp.pageReady = false;
            ytwp.isWatchPage = false;
        },
        addBodyClass: function() {
            // Insert CSS Into the body so people can style around the effects of this script.
            document.body.classList.add(scriptBodyClassId);
            ytwp.log('Applied ' + scriptBodySelector);
        },
        removeBodyClass: function() {
            document.body.classList.remove(scriptBodyClassId);
            ytwp.log('Removed ' + scriptBodySelector);
        },
    };

    ytwp.html5PlayerFix = function() {
        ytwp.log('html5PlayerFix');
        return;

        try {
            if (!uw.ytcenter // Youtube Center
                && !uw.html5Patched // Youtube+
                && (!ytwp.html5.app)
                && (uw.ytplayer && uw.ytplayer.config)
                && (uw.yt && uw.yt.player && uw.yt.player.Application && uw.yt.player.Application.create)
            ) {
                ytwp.html5.app = ytwp.html5.getPlayerInstance();
            }

            ytwp.html5.update();
            ytwp.html5.autohideControls();
        } catch (e) {
            ytwp.error(e);
        }
    }

    ytwp.fixMasthead = function() {
        ytwp.log('fixMasthead');
        var el = document.querySelector('#masthead-positioner-height-offset');
        if (el) {
            ytwp.fixMastheadElement(el);
        }
    }
    ytwp.fixMastheadElement = function(el) {
        ytwp.log('fixMastheadElement', el);
        if (el.style.height) { // != ""
            setTimeout(function(){
                el.style.height = ""
                document.querySelector('#appbar-guide-menu').style.marginTop = "";
            }, 0);
        }
    }

    JSStyleSheet.injectIntoHeader(scriptStyleId + '-focusfix', 'input#search[autofocus] { display: none; }');
    ytwp.removeSearchAutofocus = function() {
        var e = document.querySelector('input#search');
        // ytwp.log('removeSearchAutofocus', e)
        if (e) {
            e.removeAttribute('autofocus')
        }
    }

    ytwp.registerMastheadFix = function() {
        ytwp.log('registerMastheadFix');
        // Fix the offset when closing the Share widget (element.style.height = ~275px).

        observe('#masthead-positioner-height-offset', {
            attributes: true,
        }, function(mutation) {
            console.log(mutation.type, mutation)
            if (mutation.attributeName === 'style') {
                var el = mutation.target;
                if (el.style.height) { // != ""
                    setTimeout(function(){
                        el.style.height = ""
                        document.querySelector('#appbar-guide-menu').style.marginTop = "";
                    }, 0);
                }

            }
        });
    }

    //--- Material UI
    ytwp.materialPageTransition = function() {
        ytwp.log('materialPageTransition')
        ytwp.init();

        if (ytwp.isWatchUrl()) {
            ytwp.removeSearchAutofocus();
            if (enableOnLoad) {
                ytwp.event.addBodyClass();
            }
            // if (!ytwp.html5.app) {
            if (!ytwp.initialized) {
                ytwp.log('materialPageTransition !ytwp.html5.app', ytwp.html5.app)
                setTimeout(ytwp.materialPageTransition, 100);
            }
            // Focus player
            // var moviePlayer = document.querySelector('#movie_player')
            // if (moviePlayer) {
            //     moviePlayer.click()
            // }
        } else {
            ytwp.event.onDispose();
            document.body.classList.remove(scriptBodyClassId);
        }
        ytwp.onScroll();
        ytwp.fixMasthead();
        ytwp.attemptToUpdatePlayer();
    };

    //--- Listeners
    ytwp.registerListeners = function() {
        ytwp.registerMaterialListeners();
        ytwp.registerMastheadFix();
    };

    ytwp.registerMaterialListeners = function() {
        // For Material UI
        // HistoryEvent.listeners.push(ytwp.materialPageTransition);
        // HistoryEvent.startTimer();
        // HistoryEvent.inject();
        // HistoryEvent.listeners.push(console.log.bind(console));
        document.addEventListener('yt-page-data-fetched', ytwp.materialPageTransition)
        document.addEventListener('yt-navigate-finish', ytwp.materialPageTransition)

        // Debugging
        // document.addEventListener('yt-navigate-start', function(e){ ytwp.log('document.yt-navigate-start', e)})
        document.addEventListener('yt-page-data-fetched', function(e){ ytwp.log('document.yt-page-data-fetched', e)})
        document.addEventListener('yt-navigate-finish', function(e){ ytwp.log('document.yt-navigate-finish', e)})
        // document.addEventListener('yt-navigate-error', function(e){ ytwp.log('document.yt-navigate-error', e)})
        // document.addEventListener('yt-navigate-cache', function(e){ ytwp.log('document.yt-navigate-cache', e)})
        // document.addEventListener('yt-navigate-redirect', function(e){ ytwp.log('document.yt-navigate-redirect', e)})
        // document.addEventListener('yt-navigate-action', function(e){ ytwp.log('document.yt-navigate-action', e)})
        // document.addEventListener('yt-navigate-home-action', function(e){ ytwp.log('document.yt-navigate-home-action', e)})
    };

    ytwp.main = function() {
        ytwp.registerListeners();
        ytwp.init();
        ytwp.fixMasthead();
    };

    ytwp.main();

    // ytwp.updatePlayerTimerId = 0;
    ytwp.updatePlayerAttempts = -1;
    ytwp.updatePlayerMaxAttempts = 150; // 60fps = 2.5sec
    ytwp.attemptToUpdatePlayer = function() {
        // console.log('ytwp.attemptToUpdatePlayer')
        if (0 <= ytwp.updatePlayerAttempts && ytwp.updatePlayerAttempts < ytwp.updatePlayerMaxAttempts) {
            ytwp.updatePlayerAttempts = 0;
        } else {
            ytwp.updatePlayerAttempts = 0;
            ytwp.attemptToUpdatePlayerTick();
        }
        // setTimeout(ytwp.updatePlayer, 10000); /// Just in case it's not caught
    }
    ytwp.attemptToUpdatePlayerTick = function() {
        // console.log('ytwp.attemptToUpdatePlayerTick', ytwp.updatePlayerAttempts)
        if (ytwp.updatePlayerAttempts < ytwp.updatePlayerMaxAttempts) {
            ytwp.updatePlayerAttempts += 1;
            ytwp.updatePlayer();
            // ytwp.updatePlayerTimerId = setTimeout(ytwp.attemptToUpdatePlayerTick, 200);
            requestAnimationFrame(ytwp.attemptToUpdatePlayerTick);
        }
    }

    ytwp.updatePlayer = function() {
        ytwp.removeSearchAutofocus();
        ytwp.enterTheaterMode();
        ytwp.detectPlayerUnavailable();
    }

    ytwp.toggleExtension = function() {
        document.body.classList.toggle('ytwp-window-player')
        ytwp.setTheaterMode(document.body.classList.contains('ytwp-window-player'))
    }


    //--- Main
    ytwp.materialPageTransition()
    setInterval(ytwp.updatePlayer, 2500);


    //--- Keyboard Shortcut
    function childOf(child, ancestor) {
        var parent = child.parentNode
        while (parent) {
            if (parent == ancestor) {
                return true
            }
            parent = parent.parentNode
        }
        return false
    }
    function cancelIfToggleKey(validKeyCallback, e) {
        var isKey = e.key === scriptToggleKey
        var validTarget = (
            e.target === document.body
            || e.target.id === 'player-api'
            || e.target.id === 'movie_player'
            || childOf(e.target, document.querySelector('#movie_player'))
        )
        if (validTarget && isKey) {
            e.preventDefault()
            e.stopPropagation()
            console.log('cancelIfToggleKey.validKeyCallback', validKeyCallback, 'e', e)
            if (validKeyCallback) {
                validKeyCallback()
            }
        }
    }
    window.addEventListener('keydown', cancelIfToggleKey.bind(null, ytwp.toggleExtension), true)
    window.addEventListener('keyup', cancelIfToggleKey.bind(null, null), true)
    // Note: keypress is deprecated
    // https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event
    window.addEventListener('keypress', cancelIfToggleKey.bind(null, null), true)


    //--- Browser Extension
    if (typeof browser !== "undefined") {
        browser.runtime.onMessage.addListener(request => {
            if (request.id == "toggle") {
                ytwp.toggleExtension()

                return Promise.resolve({
                    enabled: document.body.classList.contains('ytwp-window-player'),
                })
            } else {
                return Promise.reject(new Error('Unreconized message.id'))
            }
        });
    }

})(window);


================================================
FILE: README.md
================================================
# Resize Youtube Player To Window Size

Moves the video to the top of the website and resizes it to the screen size. A side effect is that the resolution will auto-select 480p/720p/1080p if it fits in the window due to the video player's default behaviour.

## UserJS Hosts

* **GreasyFork:** https://greasyfork.org/scripts/811-resize-yt-to-window-size
* **OpenUserJS.org:** https://openuserjs.org/scripts/zren/Resize_YT_To_Window_Size
* ~~**Userscripts.org:** http://userscripts-mirror.org/scripts/show/153699~~

## License

GPL


================================================
FILE: ResizeRedditToWindowSize.user.js
================================================
// ==UserScript==
// @name            Resize Reddit To Window Size
// @description     Resize the video player for various sites to the window size.
// @author          Chris H (Zren / Shade)
// @namespace       https://www.github.com/Zren
// @icon            https://reddit.com/favicon.ico
// @version         50
// @include         https://*.reddit.com/*
// @grant           GM_addStyle
// ==/UserScript==

(function() {
    var movedTopPlayer = function(videoBoxElement) {
        document.body.insertBefore(videoBoxElement, document.body.firstChild);
        videoBoxElement.style.width = '100%'
        videoBoxElement.style.height = '100vh'
        videoBoxElement.style.backgroundColor = '#000'
    }

    var urlMatch = function(regexStr) {
        regexStr = regexStr.replace(/\//g, '\\/'); // Auto escape forward slashes to make url regexes more legible.
        var regex = new RegExp(regexStr);
        return regex.exec(window.location.href);
    }

    var addViewportHeight = function(selector) {
        var el = document.querySelector(selector)
        if (!el) { return }
        var style = getComputedStyle(el)
        if (style.position == "absolute") {
            var top = style.top || "0"
            el.style.top = "calc(100vh + " + top + ")"
        }
    }

    if (document.location.host.endsWith('reddit.com')) {
        var commentsRegex = /^https:\/\/www\.reddit\.com\/(r|user)\/[^\/]+\/comments\//
        if (!window.location.href.match(commentsRegex)) { return }
        var videoBoxElement = document.querySelector('.reddit-video-player-root')
        if (!videoBoxElement) { return }
        movedTopPlayer(videoBoxElement)
        var css = '.reddit-video-player-root { width: 100vw !important; height: 100vh !important; position: relative !important; display: block !important; float: none; z-index: 1000000; }'
        css += '.reddit-video-player-root .pinned-controls { display: none; }'
        css += '.pinnable-content.pinned { background-color: transparent !important; box-shadow: none !important; }'
        css += '.pinnable-content.pinned .dismiss-pinnable { display: none; }'
        css += '.pinnable-content .expando { display: none; }'
        css += '.pinnable-content .expando-button { visibility: hidden; }'
        css += '.pinnable-content.pinned { position: static !important; }'
        css += '.pinnable-content.pinned .top-matter { position: static !important; }'
        css += '.pinnable-content.pinned .midcol { position: static !important; }'
        css += 'html, body { padding-left: 0 !important; padding-right: 0 !important }'
        GM_addStyle(css)

        setTimeout(function(){
            addViewportHeight('.side #search')
            addViewportHeight('.side .submit-link')
            addViewportHeight('.side .submit-text')
            addViewportHeight('.linkinfo')
        }, 2000)
    }

    GM_addStyle('html::-webkit-scrollbar { width: 0; height: 0; } body::-webkit-scrollbar { width: 0; height: 0; }')
    GM_addStyle('html { scrollbar-width: none; } body { scrollbar-width: none; }')
})();


================================================
FILE: ResizeVideoDescription.md
================================================
Resizes the following sites

* https://www.crunchyroll.com/
* https://docs.google.com/file/
* https://drive.google.com/drive/
* https://vimeo.com/ (Will also autoplay video)
* http://www.onepieceofficial.com/
* https://www.youpak.com/
* http://olympics.cbc.ca/
* ~~http://www.dailymotion.com/ (Will also hide control bar faster)~~
* https://streamable.com/
* https://www.globaltv.com/shows/the-late-show-with-stephen-colbert/
* https://www.much.com/shows/south-park/episode/
* https://www.ctvnews.ca/
* https://watch.cbc.ca/live/
* https://www.ctv.ca/ (Will also unmute, and reload the page to workaround uBlockOrigin bug)
* https://www.funimation.com/
* https://www.crave.ca/
* https://tubitv.com/
* https://tv.bell.ca/

# Suggestions
* Use [Resize YT To Window Size](https://greasyfork.org/en/scripts/811-resize-yt-to-window-size) for YouTube. It has it's own script since YouTube's website is much more complicated and has many edge cases.
* Experimental support for hiding scrollbar in Firefox v63. Go to `about:config` and set `layout.css.scrollbar-width.enabled` to `true`, then restart Firefox.

## Screenshots

![](https://i.imgur.com/bdoXOQc.png)
![](https://i.imgur.com/K7uvIhp.png)
![](https://i.imgur.com/CmxBBdj.png)


================================================
FILE: ResizeVideoToWindowSize.user.js
================================================
// ==UserScript==
// @name            Resize Video To Window Size
// @description     Resize the video player for various sites to the window size.
// @author          Chris H (Zren / Shade)
// @namespace       http://xshade.ca
// @version         67
// @include         https://www.crunchyroll.com/*
// @include         https://beta.crunchyroll.com/*
// @include         https://static.crunchyroll.com/vilos-v2/web/vilos/player.html*
// @include         https://docs.google.com/file/*
// @include         https://drive.google.com/drive/*
// @include         https://drive.google.com/file/*
// @include         https://vimeo.com/*
// @include         http://onepieceofficial.com/videos.aspx*
// @include         http://www.onepieceofficial.com/videos.aspx*
// @include         https://www.youpak.com/watch*
// @include         https://olympics.cbc.ca/video/*
// @include         https://olympics.cbc.ca/divaPlayer/*
// @include         http://www.dailymotion.com/*
// @include         https://www.dailymotion.com/*
// @include         https://streamable.com/*
// @include         https://www.globaltv.com/shows/*
// @include         https://watch.globaltv.com/video/*
// @include         https://www.much.com/shows/south-park/episode/*/*/
// @include         http://*.ctvnews.ca/*
// @include         https://watch.cbc.ca/live/channel/*
// @include         https://watch.cbc.ca/live/*
// @include         https://www.ctv.ca/shows/*
// @include         https://www.ctv.ca/video/*
// @include         https://www.ctv.ca/*/Video*
// @include         https://www.ctv.ca/Movie/*
// @include         https://www.funimation.com/shows/*
// @include         https://www.funimation.com/player/*
// @include         https://www.crave.ca/*
// @include         https://tubitv.com/*
// @include         https://tv.bell.ca/*
// @grant           GM_addStyle
// ==/UserScript==

(function() {
    var fixedOverlayPlayer = function(selector) {
        var css = selector + "{";
        css += "position: fixed;";
        css += "top: 0;";
        css += "left: 0;";
        css += "right: 0;";
        css += "bottom: 0;";
        css += "}";
        GM_addStyle(css);
    };

    var absoluteTopPlayer = function(selector, staticSelectors) {
        var css = selector + "{";
        css += "position: absolute;";
        css += "top: 0;";
        css += "left: 0;";
        css += "width: 100vw;";
        css += "height: 100vh;";
        css += "padding: 0;";
        css += "margin: 0;";
        css += "}";
        css += "body {";
        css += "margin-top: 100vh;";
        css += "margin-top: 100vh;";
        css += "padding-top: 0;";
        css += "}";
        if (staticSelectors) {
            css += staticSelectors + "{";
            css += "position: static";
            css += "}";
        }
        GM_addStyle(css);
    };

    var movedTopPlayer = function(videoBoxElement) {
        document.body.insertBefore(videoBoxElement, document.body.firstChild);
        videoBoxElement.style.width = '100%';
        videoBoxElement.style.height = '100%';
        videoBoxElement.style.backgroundColor = '#000';
    };

    var waitFor = function(selector, callback) {
        var tick = function(){
            var e = document.querySelector(selector);
            if (e) {
                callback(e);
            } else {
                setTimeout(tick, 100);
            }
        };
        tick();
    };

    var bindJWPlayerSpacebar = function() {
        window.addEventListener('keydown', function(e){
            if (e.key == ' ' && e.target == document.body) {
                var video = document.querySelector('.jwplayer video')
                if (video) {
                    e.preventDefault();
                    if (video.paused) {
                        video.play()
                    } else {
                        video.pause()
                    }
                }
            }
        });
    };

    var urlMatch = function(regexStr) {
        regexStr = regexStr.replace(/\//g, '\\/'); // Auto escape forward slashes to make url regexes more legible.
        var regex = new RegExp(regexStr);
        return regex.exec(window.location.href);
    };

    if (document.location.host.endsWith('crunchyroll.com')) {
        // console.log('doc loc', document.location)
        // console.log('win loc', window.location)
        if (document.location.hostname == 'www.crunchyroll.com' || document.location.hostname == 'beta.crunchyroll.com') {
            var rvtwsHeaderClass = 'rvtws-header-hidden'
            var css = ''
            css += '.erc-header.'+rvtwsHeaderClass+' { position: absolute; }'
            css += '.erc-header.'+rvtwsHeaderClass+' .header-content { opacity: 0; transition: opacity: 0.1s; }'
            css += '.erc-header.'+rvtwsHeaderClass+' .header-content:hover { opacity: 1; }'
            css += '.erc-watch-episode-layout .video-player-wrapper { max-height: 100vh; height: 100vh; display: flex; }'
            // css += '.erc-watch-episode-layout .video-player { height: 56.25vw; align-self: center; }'
            GM_addStyle(css)
            function updateHeader() {
                var ercHeader = document.querySelector('.erc-header')
                var ercWatchEpisode = document.querySelector('.erc-watch-episode')
                if (ercHeader) {
                    if (ercWatchEpisode) {
                        ercHeader.classList.add(rvtwsHeaderClass)
                    } else {
                        ercHeader.classList.remove(rvtwsHeaderClass)
                    }
                }
            }
            window.addEventListener('popstate', updateHeader)
            setInterval(updateHeader, 1000)
            updateHeader()
        } else if (document.location.hostname == 'static.crunchyroll.com' && document.location.pathname == '/vilos-v2/web/vilos/player.html') {
            GM_addStyle('#vilosRoot { height: 100vh !important; }');
            GM_addStyle('#vilosControlsContainer > div:first-child { margin-top: 3.75rem; }'); // Make room for header
        }
    } else if (document.location.href.startsWith('https://docs.google.com/file/')) {
        fixedOverlayPlayer('#drive-viewer-video-player-object-0');
        var css = 'body:not(:hover) .ytp-chrome-bottom { opacity: 0 !important; }';
        css += 'body:not(:hover) .drive-viewer-toolstrip { opacity: 0 !important; }';
        GM_addStyle(css);
    } else if (document.location.href.startsWith('https://drive.google.com/')) {
        fixedOverlayPlayer('.drive-viewer-video-player');
        var css = '.drive-viewer-toolstrip { opacity: 0 !important; }';
        css += '.drive-viewer-toolstrip:hover { opacity: 1 !important; }';
        GM_addStyle(css);
    } else if (document.location.href.startsWith('https://vimeo.com/')) {
        if (! /\/\d+/.exec(document.location.pathname))
            return;
        var css = '.js-player_area-wrapper, .player_area-wrapper, .player_area, .player_container, .player, .video-wrapper, .video, .video * { width: 100vw !important; height: 100vh !important; max-height: 100vh !important; }';
        css += '.vp-player-layout { left: 0 !important; top: 0 !important; width: 100vw !important; height: 100vh !important; }';
        css += '.clip_main > *:not(.player_area-wrapper) { margin-top: 70px; }';
        css += '.VimeoBrand_ColorRibbon, .body_ribbon, .topnav_desktop, .topnav_mobile { position: absolute; top: 100vh; width: 100%; }';
        css += '.topnav_desktop { top: calc(100vh + 5px); }';
        GM_addStyle(css);

        // autoplay
        function tick() {
            var e = document.querySelector('button.play[aria-label="Play"]');
            if (e) {
                e.click();
            } else {
                setTimeout(tick, 100);
            }
        }
        setTimeout(tick, 100);
    } else if (document.location.host.endsWith('onepieceofficial.com')) {
        movedTopPlayer(document.querySelector('#FUNimationVideo'));
    } else if (document.location.host.endsWith('youpak.com')) {
        movedTopPlayer(document.querySelector('.videoWrapper'))
        var css = 'body > .container { padding-top: 60px; }'
        css += '.navbar-fixed-top { position: absolute; top: 100vh; }'
        css += 'body { padding-top: 0; }'
        GM_addStyle(css)
    } else if (document.location.host == 'olympics.cbc.ca') {
        console.log(document.location.pathname, document.location.pathname.match(/\/video\/([^\/]+)\/([^\/]+)(\/?)/))
        if (document.location.pathname.match(/\/video\/([^\/]+)\/([^\/]+)(\/?)/)) {
            var css = '.cbc-video--player-wrapper { position: static !important; }'
            css += '.cbc-video {'
            css += '    position: absolute !important;'
            css += '    top: 0 !important;'
            css += '    left: 0 !important;'
            css += '    padding: 0px !important;'
            css += '    margin: 0px !important;'
            css += '    width: 100% !important;'
            css += '    height: 100vh !important;'
            css += '}'
            css += 'figure.cbc-video--thumb-wrapper, a[data-js-hook="play-video"] picture img { max-height: 100vh !important; }'
            css += '.or-podium .or-box { position: static !important; }'
            css += '.or-podium .col-xs-1, .or-podium .col-sm-1, .or-podium .col-md-1, .or-podium .col-lg-1, .or-podium .col-xs-2, .or-podium .col-sm-2, .or-podium .col-md-2, .or-podium .col-lg-2, .or-podium .col-xs-3, .or-podium .col-sm-3, .or-podium .col-md-3, .or-podium .col-lg-3, .or-podium .col-xs-4, .or-podium .col-sm-4, .or-podium .col-md-4, .or-podium .col-lg-4, .or-podium .col-xs-5, .or-podium .col-sm-5, .or-podium .col-md-5, .or-podium .col-lg-5, .or-podium .col-xs-6, .or-podium .col-sm-6, .or-podium .col-md-6, .or-podium .col-lg-6, .or-podium .col-xs-7, .or-podium .col-sm-7, .or-podium .col-md-7, .or-podium .col-lg-7, .or-podium .col-xs-8, .or-podium .col-sm-8, .or-podium .col-md-8, .or-podium .col-lg-8, .or-podium .col-xs-9, .or-podium .col-sm-9, .or-podium .col-md-9, .or-podium .col-lg-9, .or-podium .col-xs-10, .or-podium .col-sm-10, .or-podium .col-md-10, .or-podium .col-lg-10, .or-podium .col-xs-11, .or-podium .col-sm-11, .or-podium .col-md-11, .or-podium .col-lg-11, .or-podium .col-xs-12, .or-podium .col-sm-12, .or-podium .col-md-12, .or-podium .col-lg-12 { position: static; }'
            css += 'body:not(.cbc-main-page) { padding-top: 100vh; }'
            GM_addStyle(css);
            var playVideoButton = document.querySelector('a[data-js-hook="play-video"]')
            if (playVideoButton) {
                playVideoButton.click()
            }
        } else if (document.location.pathname.startsWith('/divaPlayer')) {
            var css = '#videoContainer:not(:hover) > .caption { opacity: 0; }'
            css += '#videoContainer:not(:hover) .controlbar-diva { opacity: 0 !important; }'
            css += '#videoContainer:not(:hover) #icon-menu-diva { opacity: 0; }'
            css += '#videoContainer:not(:hover) diva-simple-controls { opacity: 0 !important; }'
            GM_addStyle(css);
        } else {
            return; // Keep scrollbars
        }
    } else if (false && document.location.host.endsWith('www.dailymotion.com')) {
        var css = '#player:not(:hover) .dmp_will-transition.dmp_is-transitioned--fadeinslide { opacity: 0; }';
        if (document.location.pathname.startsWith('/playlist')) {
            css += '#player_container { height: 100vh!important; width: 100vw!important; }';
            css += '#playerv5-iframe { width: 100% !important; height: 100% !important; }'; // playlists
            css += '.sd_header.sd_header--fixed { top: 100vh; position: absolute; }';
            css += '#content { margin-top: 60px; }';
            movedTopPlayer(document.querySelector('#player_container'));
            absoluteTopPlayer('#player_container');

            GM_addStyle(css);

        } else if (document.location.pathname.startsWith('/video')) {
            //css +='.main-container-player { display: none; }';
            //css += '#player { height: 100vh!important; width: 100vw!important; }';
            css += '.Player { height: 100vh!important; width: 100vw!important; }';
            css += '.Player { top: 0!important; left: 0!important; }';
            css += 'header { position: absolute!important; top: 100vh !important; }';
            css += 'footer { margin-top: 50px; }';
            css += 'div[class^="Video__placeholder___"] { margin-top: -180px; height: 100vh!important; }';
            GM_addStyle(css);
            document.addEventListener('load',function(){
                movedTopPlayer(document.querySelector('.Player'));
            });
        }

    } else if (document.location.host.endsWith('streamable.com')) {
        if (document.location.pathname == '/') {
            return;
        }
        var css = '#player-content, #player.container .media-container, #player.container #filler, #player.container .player { max-width: 100% !important; width:100%; }';
        css += '#player.container #filler { padding-bottom: 100vh !important; }';
        css += '.player { background: #000; }';
        css += '#player.container .player { display: flex; }';
        css += '.player, #player.container video { max-height: 100vh; object-fit: contain; }';
        css += '#player > div[style="height:15px;"] { display: none; }';
        css += '#player.container .topbanner { display: none; }';
        GM_addStyle(css);
    } else if (document.location.host.endsWith('globaltv.com')) {
        var css = 'html, body, #root, .App, .Video {'
        css += 'min-height: 100%; height: 100%; max-height: 100%;'
        css += 'min-width: 100%; width: 100%; max-width: 100%;'
        css += '}'
        css += 'body { overflow-y: auto; }'
        GM_addStyle(css);
        waitFor('.jwplayer', function(jwPlayerElement) {
            waitFor('.jwplayer video', function(videoElement) {
                setTimeout(function() {
                    videoElement.muted = false;
                }, 200)
            });
        });
        bindJWPlayerSpacebar();
    } else if (document.location.host.endsWith('much.com')) {
        var css = '#TopVideoWidgetSection, #ShowNav, #MainHeader, #MastHeadTakeover { display: none; }';
        css += '#ShowTop #PlayerWrapper, #ShowTop .container-fluid, #ShowTop #ShowInfo, #ShowTop {';
        css += 'margin: 0 !important; padding: 0 !important;';
        css += 'width: 100vw !important; height: 100vh !important; max-width: 100vw !important; max-height: 100vh !important;';
        css += '}';
        css += '#ShowTop #ShowInfo #EpisodeInfo { margin-top: 0 !important; }';
        css += '.jwplayer { max-height: 100vh; }';
        css += '#EpisodeInfo .new-episodes { display: none !important; }';
        GM_addStyle(css);
    } else if (document.location.host.endsWith('ctvnews.ca')) {
        if (window.location.pathname == '/latest') {
            // Redirect to latest video
            document.body.style.opacity = "0"
            document.documentElement.style.transition = "background 0.4s"
            document.documentElement.style.background = "#000"
            var latestVideoLink = document.querySelector('.mainnavigation + .drop_down + script + .drop_down > .drop_down_element_container > div > div > ul > li:first-child > a')
            if (latestVideoLink) {
                window.location.href = latestVideoLink.href
            }
        } else if (window.location.pathname == '/video') {
            var contentWrapper = document.querySelector('body > .content > .video-header > .content-wrapper')
            if (contentWrapper) {
                var header = document.querySelector('body > header')
                document.body.insertBefore(contentWrapper, header)
                var mediaplayerdiv = document.querySelector('#mediaplayerdiv')

                contentWrapper.querySelector('.topname').style.display = "none"
                contentWrapper.style.width = "100%"
                contentWrapper.style.height = "100vh"
                contentWrapper.style.maxWidth = "100vw"
                contentWrapper.style.maxHeight = "100vh"
                contentWrapper.style.background="#000"

                function onWindowResize() {
                    var viewportWidth = document.documentElement.clientWidth
                    var viewportHeight = document.documentElement.clientHeight
                    var translate = "translate(" + ((viewportWidth - 960)/2) + "px, " + ((viewportHeight - 540)/2) + "px)"
                    var scale = "scale(" + Math.min(viewportWidth / 960, viewportHeight / 540) + ")"
                    mediaplayerdiv.style.transform = translate + " " + scale
                }
                window.addEventListener('resize', onWindowResize);
                onWindowResize();
                return; // Keep scrollbars
            }
        } else {
            return; // Keep scrollbars
        }
    } else if (document.location.host.endsWith('watch.cbc.ca')) {
        var css = '#masthead { position: absolute; z-index: 1; width: 100%; opacity: 0; transition: opacity 250ms ease-in-out; }';
        css += '#masthead:hover { opacity: 1; }';
        css += '.regional-channel .container { max-width: 100%; }';
        css += '.player-container.live, .jwplayer.jw-flag-aspect-mode { max-height: 100vh; }';
        css += '.jwplayer.jw-stretch-uniform video { object-fit: contain !important; }';
        css += '.regional-channel footer.regional-channel-footer, section.content-article.live { padding: 10px 0; }';
        css += 'section.content-article.live-premium { display: none; }';
        css += '.upgrade-banner, .live-premium, iframe.zEWidget-launcher { display: none; }';
        css += '.upgrade-banner + .app-container.with-banner-large { top: 0; }';
        css += '.content-article { padding-top: 0; padding-bottom: 0; }';
        css += '.content-section.live-detail-layout { max-width: 100%; }';
        GM_addStyle(css);
    } else if (document.location.host.endsWith('www.ctv.ca')) {
        var css = ''
        css += 'header.navigation { opacity: 0; position: fixed; }'
        css += 'header.navigation:hover { opacity: 1; }'
        css += '.main { padding-top: 0 !important; }'
        css += '#vidi-player-standalone { margin: 0vw 0vw 0; }'
        css += 'div[class*="VidiPlayerstyles__VidiPlayerStandAloneContainer"] { margin: 0vw 0vw 0; }'
        css += '.jwplayer.jw-flag-aspect-mode { min-height: 100vh !important; height: 100vh !important; max-height: 100vh !important; }'
        css += 'div[class*="BrowserNotificationstyles"] { display: none; }'
        css += 'div[class^="ArrowBackstyles__ButtonContainer"] { display: none; }'

        css += 'div[class^="globalStyles__MainContainer"] { padding-top: 0 !important; }'
        css += 'div[class^="VidiPlayerstyles__VidiPlayerPageContainer"] { margin: 0 !important; }'
        GM_addStyle(css);
        waitFor('.jwplayer', function(jwPlayerElement) {
            waitFor('.jwplayer video', function(videoElement) {
                setTimeout(function() {
                    videoElement.muted = false;
                }, 200)
            });
        });
        bindJWPlayerSpacebar();
        var reverseEpisodeOrder = [
            '/shows/the-daily-show-with-trevor-noah',
        ]
        waitFor('ul[class*="Episodesstyles__EpisodeList"]', function(ul) {
            if (reverseEpisodeOrder.indexOf(document.location.pathname) >= 0) {
                for (var i = 0; i < ul.children.length; i++) {
                    ul.insertBefore(ul.children[i], ul.firstChild)
                }
            }
        });
        setInterval(function(){
            var e = document.querySelector('#__next div:not(.App)')
            if (e) {
                var h2 = e.querySelector('h2')
                if (h2 && h2.textContent == 'An unexpected error has occurred.') {
                    // CTV doesn't like uBlockOrigin, so reload the page to workaround the AJAX React links breaking.
                    window.location.reload()
                }
            }
        }, 100);
    } else if (document.location.host.endsWith('funimation.com')) {
        console.log('funimation.com')
        var videoBoxElement = document.querySelector('.video-player-section .video-player-container');
        console.log('videoBoxElement', videoBoxElement)
        if (videoBoxElement) {
            movedTopPlayer(videoBoxElement);
            videoBoxElement.classList.remove('col-md-10');

            var css = 'html, body { width: 100%; height: 100%; }';
            css += '.video-player-container { width: 100vw !important; height: 100vh !important; }';
            css += '#funimation-main-site-header { position: absolute; top: 100vh; }';
            GM_addStyle(css);
        } else {
            console.log('location', document.location)
            waitFor('#brightcove-player', function(player){
                console.log('player', player)
                player.removeAttribute('muted')
                waitFor('.vjs-mute-control.vjs-vol-0', function(muteButton){
                    console.log('muteButton', muteButton)
                    muteButton.click()
                })
            })
        }
    } else if (document.location.host.endsWith('crave.ca')) {
        if (document.location.pathname.startsWith('/live')) return;
        var videoBoxElement = document.querySelector('video-player');
        if (!videoBoxElement) return;
        var css = 'footer, .back-button-wrapper, #mega-menu { display: none !important; }';
        css += '.container-site-margin { margin-left: 0; margin-right: 0; }';
        css += '.web-videoplayer { margin: 0; }';
        css += 'html .jwplayer.jw-flag-aspect-mode { height: 100vh !important; }';
        GM_addStyle(css);
    } else if (document.location.host.endsWith('tubitv.com')) {
        var css = 'header { transition: transform .3s, opacity .3s !important; }';
        css += 'header.hide-header { opacity: 0 !important }';
        css += 'header.hide-header:hover { opacity: 1 !important; }';
        css += 'header + div > div:first-child > div:first-child > div:nth-child(2) { top: 0 !important; left: 0 !important; width: 100% !important; height: 100vh !important; }';
        css += 'header + div > div:first-child > div:first-child > div:nth-child(2) > div:first-child > section { padding-top: 0 !important; height: 100vh !important; }';
        css += 'header + div > div:first-child > div:first-child > div:nth-child(2) > div:first-child > section > div > div:nth-child(2) > div:first-child { background-image: linear-gradient(0deg,rgba(0,0,0,0), rgba(0,0,0,0.25) 30%, rgba(0, 0, 0, 1) 90%); }';
        css += 'header + div > div:first-child > div:first-child > div:nth-child(2) > div:first-child > section > div > div:nth-child(2) > div:nth-child(2) { background-image: linear-gradient(180deg,rgba(0,0,0,0), rgba(0,0,0,0.25) 30%, rgba(0, 0, 0, 1) 90%); }';
        css += '#captionsComponent > span { background: none !important; font-size: 3rem !important;';
        css += 'text-shadow: 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000, 0 0 0.5rem #000;';
        css += '}';
        GM_addStyle(css);
        var updateHeader = function() {
            var header = document.querySelector('header')
            if (header) {
                var video = document.querySelector('video')
                if (video) {
                    header.classList.add('hide-header')
                } else {
                    header.classList.remove('hide-header')
                }
            }
        }
        updateHeader()
        setInterval(updateHeader, 1000)
    } else if (document.location.host.endsWith('tv.bell.ca')) {
        if (!document.location.pathname.startsWith('/watch/')) return;
        //let videoBoxElement = document.querySelector('video[playsinline]');
        //if (!videoBoxElement) return;
        waitFor('video[playsinline]', function(videoBoxElement){
            let css = ''
            css += '.bg-greyscale-black.w-capped { position: absolute !important; top: calc((var(--headerHeight) + 100vh) * -1 ) !important; height: 100vh !important; }';
            css += '.bg-greyscale-black.w-full { position: absolute !important; top: -100vh !important; height: 100vh !important; }';
            css += 'body { padding-top: 100vh !important; }';
            css += '[class*="&_.bmpui-ui-subtitle-label]:!bg-greyscale-black-70"].h-full.w-full.justify-center { max-width: 100% !important; }'
            css += 'header[class="bg-greyscale-03 virgin:bg-tertiary-medium flex"][aria-label="Global"] { display: none !important; }'
            console.log('css', css)
            GM_addStyle(css);
        })
    }

    GM_addStyle('html::-webkit-scrollbar { width: 0; height: 0; } body::-webkit-scrollbar { width: 0; height: 0; }');
    GM_addStyle('html { scrollbar-width: none; } body { scrollbar-width: none; }');
})();


================================================
FILE: YTDocs.md
================================================
# Youtube Player Documentation

## 2023 Oct 31

https://www.youtube.com/s/desktop/9e7f5697/jsbin/desktop_polymer_enable_wil_icons.vflset/desktop_polymer_enable_wil_icons.js

Note, `yt-navigate-start` does not fire on web browser Back button ([Issue #76](https://github.com/Zren/ResizeYoutubePlayerToWindowSize/issues/76)). `document` events fire before `window` events.

```js
document.addEventListener('yt-navigate-start', function(){ console.log('document.yt-navigate-start', arguments)})
document.addEventListener('yt-navigate-finish', function(){ console.log('document.yt-navigate-finish', arguments)})
document.addEventListener('yt-navigate-error', function(){ console.log('document.yt-navigate-error', arguments)})
document.addEventListener('yt-navigate-redirect', function(){ console.log('document.yt-navigate-redirect', arguments)})
document.addEventListener('yt-navigate-cache', function(){ console.log('document.yt-navigate-cache', arguments)})
document.addEventListener('yt-navigate-action', function(){ console.log('document.yt-navigate-action', arguments)})
document.addEventListener('yt-navigate-home-action', function(){ console.log('document.yt-navigate-home-action', arguments)})
document.addEventListener('yt-page-data-fetched', function(){ console.log('document.yt-page-data-fetched', arguments)})
window.addEventListener('yt-navigate-start', function(){ console.log('window.yt-navigate-start', arguments)})
window.addEventListener('yt-navigate-finish', function(){ console.log('window.yt-navigate-finish', arguments)})
window.addEventListener('yt-navigate-error', function(){ console.log('window.yt-navigate-error', arguments)})
window.addEventListener('yt-navigate-redirect', function(){ console.log('window.yt-navigate-redirect', arguments)})
window.addEventListener('yt-navigate-cache', function(){ console.log('window.yt-navigate-cache', arguments)})
window.addEventListener('yt-navigate-action', function(){ console.log('window.yt-navigate-action', arguments)})
window.addEventListener('yt-navigate-home-action', function(){ console.log('window.yt-navigate-home-action', arguments)})
window.addEventListener('yt-page-data-fetched', function(){ console.log('window.yt-page-data-fetched', arguments)})
```

```js
    T8c = function (a, b) {
      a.listen(b, 'yt-navigate-start', 'onYtNavigateStart');
      a.listen(b, 'yt-navigate-finish', 'onYtNavigateFinish');
      a.listen(b, 'yt-navigate-error', 'onYtNavigateError');
      a.listen(b, 'yt-page-data-fetched', 'onYtPageDataFetched');
      a.listen(b, 'yt-navigate-redirect', 'onYtNavigateRedirect')
    };
    f = C6.prototype;
    f.detached = function () {
      var a = rp().resolve(BE);
      this.unlisten(a, 'yt-navigate-start', 'onYtNavigateStart');
      this.unlisten(a, 'yt-navigate-finish', 'onYtNavigateFinish');
      this.unlisten(a, 'yt-navigate-error', 'onYtNavigateError');
      this.unlisten(a, 'yt-page-data-fetched', 'onYtPageDataFetched');
      this.unlisten(document, 'yt-navigate-cache', 'onYtNavigateCache');
      this.unlisten(a, 'yt-navigate-redirect', 'onYtNavigateRedirect');
      this.ytActionHandlerBehavior.unregisterActionMap(this.appBehaviorActionMap)
    };
```

```js
a.actionMap = {
'yt-command-executor-command': 'handleCommandWithCommandHandler',
'yt-dark-mode-toggled-action': 'onDarkModeToggledAction',
'yt-edu-dismiss-action': 'handleEduDismissAction',
'yt-edu-impression-action': 'handleEduImpressionAction',
'yt-navigate-action': 'onYtNavigateAction',
'yt-navigate-home-action': 'onYtNavigateHomeAction',
'yt-player-fullscreen': 'onPlayerFullscreen',
'yt-register-create-family-dialog': 'onYtRegisterCreateFamilyDialog',
'yt-select-country-command': 'handleSelectCountryCommand',
'yt-select-language-command': 'handleSelectLanguageCommand',
'yt-clear-url-param-command': 'handleClearUrlParamCommand',
'yt-set-cookie-command': 'onSetCookieCommand',
'yt-set-pref-storage-entry-command': 'onSetPrefStorageEntryCommand',
'yt-set-local-storage-command': 'onSetLocalStorageCommand',
'yt-set-push-notifications-enabled-command': 'onSetPushNotificationsEnabledCommand',
'yt-signal-action-copy-debug-data': 'onYtSignalActionCopyDebugData',
'yt-signal-action-enable-chrome-notifications': 'onYtSignalActionEnableChromeNotifications',
'yt-signal-action-toggle-restricted-mode-on': 'onYtSignalActionToggleRestrictedModeOnAction',
'yt-signal-action-toggle-restricted-mode-off': 'onYtSignalActionToggleRestrictedModeOffAction',
'yt-signal-action-confirm-mentions-edu': 'onYtSignalActionConfirmMentionsEdu',
'yt-signal-action-record-mentions-edu-impression': 'onYtSignalActionRecordMentionsEduImpression',
'yt-signal-action-show-keyboard-shortcut-dialog': 'onYtSignalActionShowKeyboardShortcutDialog',
'yt-signal-action-skip-navigation': 'onYtSignalActionSkipNavigation',
'yt-signal-action-request-persistent-storage': 'onYtSignalActionRequestPersistentStorage',
'yt-timed-command': 'onYtTimedCommand',
'yt-window-resized': 'onWindowResized',
'yt-window-scrolled': 'onWindowScrolled',
'yt-persist-subscriptions-display-preferences-command': 'handlePersistSubscriptionsDisplayPreferencesCommand',
'yt-invoke-instrument-manager-action': 'onInvokeInstrumentManagerAction',
'yt-entity-update-command': 'handleEntityUpdateCommand',
'yt-web-native-share-command': 'handleWebNativeShareCommand',
'yt-confirm-dialog-endpoint': 'handleConfirmDialogEndpoint',
'yt-ad-feedback-endpoint': 'handleOpenPopupNavigationEndpoints',
'yt-create-backstage-post-dialog-endpoint': 'handleOpenPopupNavigationEndpoints',
'yt-manage-purchase-endpoint': 'handleOpenPopupNavigationEndpoints',
'yt-modal-endpoint': 'handleOpenPopupNavigationEndpoints',
'yt-unlimited-family-flow-endpoint': 'handleOpenPopupNavigationEndpoints',
'yt-ypc-cancel-survey-endpoint': 'handleOpenPopupNavigationEndpoints',
'yt-register-promo-command': 'handleYtRegisterPromoCommand',
'yt-location-collection-command': 'onYtLocationCollectionCommand',
'yt-get-location-command': 'onYtGetLocationCommand',
'yt-log-flow-logging-event-command': 'logFlowLoggingEventCommand',
'yt-save-command-to-session-storage-action': 'handleSaveCommandToSessionStorage',
'yt-show-dma-consent-flow-command': 'handleShowDmaConsentFlow',
'yt-signal-action-show-dma-consent-flow': 'handleShowDmaConsentFlow',
'yt-signal-action-toggle-dark-theme-on': 'handleSignalActionToggleDarkThemeOn',
'yt-signal-action-toggle-dark-theme-off': 'handleSignalActionToggleDarkThemeOff',
'yt-signal-action-toggle-dark-theme-device': 'handleSignalActionToggleDarkThemeDevice',
'yt-select-active-identity-endpoint': 'handleSelectActiveIdentityEndpointInternal',
'yt-update-permission-role-command': 'handleUpdatePermissionRoleCommand',
'yt-channel-creation-form-endpoint': 'handleYtChannelCreationFormEndpoints',
'yt-google-payment-billing-command': 'handleCommandWithCommandHandler'
}
```


## 2017 May 11

`base.js` defines the classes and exposes them at `window._yt_player`
a watch page will add a script tag that sets `window.ytplayer.config`
then immeditately calls `Application.create()`, but doesn't expose the app instance.

```js
ytplayer.load = function() {
  yt.player.Application.create("player-api", ytplayer.config);
  ytplayer.config.loaded = true;
};
(function() {
  if (!!window.yt && yt.player && yt.player.Application) {
    ytplayer.load();
  }
}());
```

`Application.create` does store the app instance in a list, 
but it's no longer accessible.
Reinitializing the player will work, but may cause a 2nd `#movie_player` element to be created.

`Application.create()` will call

```js
O1 = function(a, b) {
    g.M.call(this);
    var c = this;
    this.ca = Xia(b);
    var d = this.ca.args || {};
    this.Z = new zO(d);
    g.N(this, this.Z);
    this.Z.experiments.g("legacy_autoplay_flag") || "detailpage" != this.Z.g || (d.autoplay = "1");
    this.Bc = dO("detailpage" == this.Z.g && "blazer" != this.Z.o, d.enablesizebutton);
    this.oa = dO(!1, d.player_wide);
    this.V = this.Z.Fb && dO(!1, d.external_list);
    this.va = (this.qc = this.Z.Fb && dO(!1, d.external_play_video)) && this.Z.experiments.g("player_unified_fullscreen_transitions");
    this.P = new g.BL(this);
    g.N(this, this.P);
    Gc = function(a, b) {
        g.kE(b, "WARNING")
    }
    ;
    this.Oa = null;
    this.K = new g.cD;
    this.ba = new g.cD;
    this.da = new N1(this.ba);
    this.da.pause();
    this.g = new PU(this);
    g.N(this, this.g);
    this.J = new PU(this,1);
    g.N(this, this.J);
    this.F = new bZ(this);
    g.N(this, this.F);
    this.O = 1;
    this.Va = {};
    this.M = this.Z.storeUserVolume ? Cja() : {
        volume: 100,
        muted: this.Z.mute
    };
    this.aa = this.Z.Fb ? new YJ(this,1) : new bJ(this,1);
    g.N(this, this.aa);
    this.D = null;
    this.Ra = {};
    d = {};
    this.xb = (d.internalAbandon = this.RL,
    d.internalvideodatachange = this.QL,
    d.playbackready = this.SL,
    d.playbackstarted = this.TL,
    d.statechange = this.UL,
    d.signatureexpired = this.YO,
    d);
    this.A = Lna(this);
    g.N(this, this.A);
    this.G = new zP(this.Z,"",this.A);
    this.o = Mna(this);
    d = {};
    this.tc = (d.airplayactivechange = this.HL,
    d.airplayavailabilitychange = this.IL,
    d.beginseeking = this.cM,
    d.endseeking = this.QM,
    d.internalAbandon = this.iN,
    d.internalaudioformatchange = this.WL,
    d.internalvideodatachange = this.vr,
    d.internalvideoformatchange = this.BP,
    d.liveviewshift = this.oN,
    d.playbackstalledatstart = this.eP,
    d.progresssync = this.RI,
    d.seekto = this.SI,
    d.onLoadProgress = this.pN,
    d.onVideoProgress = this.VI,
    d.playbackready = this.lO,
    d.statechange = this.cA,
    d.connectionissue = this.AM,
    d.newelementrequired = this.SN,
    d.heartbeatparams = this.OI,
    d.videoelementevent = this.TI,
    d);
    this.C = null;
    this.ra = new zZ(5,function(a) {
        a != g.WU(c, a.getPlayerType()) && a.dispose()
    }
    );
    g.N(this, this.ra);
    this.zb = this.Bb = -1;
    this.sb = new g.nt(this.F.Zf,16,this.F);
    g.N(this, this.sb);
    this.tb = !1;
    this.fa = !0;
    this.sa = this.Na = this.B = null;
    this.Hb = !1;
    this.Tb = this.sc = null;
    this.ob = this.ga = 0;
    this.ka = this.Ja = !1;
    this.Fa = this.ha = null;
    this.P.T(this.g, "crn_appapi", this.OL);
    this.P.T(this.g, "crx_appapi", this.PL);
    this.P.T(this.g, "crn_appad", this.mz);
    this.P.T(this.g, "crx_appad", this.mz);
    this.P.T(this.g, "presentingplayerstatechange", this.QI);
    this.P.T(this.g, "resize", this.IO);
    this.F.Ia(g.ae(a));
    this.Xb = this.Z.experiments.g("html5_enable_embedded_player_visibility_signals") && this.Z.A ? new BZ(this.F.element) : null;
    g.N(this, this.Xb);
    g.ND = this.Z.ba;
    Nna(this);
    this.G.o("fs");
    Ona(this);
    this.Fa = new L1(this.g);
    this.A.C = this.Fa;
    this.Fa.init();
    g.dV(this.J, "init")
}
```

The `g` variable is an alias for `_yt_player`.
We can monkey patch `g.WU` since it's passed the "c = this" variable as it's first argument.

```js
g.WU=function(a,b){return b?1==b?a.o:a.Ra[b]||null:a.C}; // Chrome
g.ZU=function(a,b){return b?1==b?a.o:a.Ra[b]||null:a.C}; // Firefox
```

We then take that instance and patch `app[key1][key2]()`
where the value of `key1` has a property called element that points to `#movie_player`

```js
app[key1].element = #movie_player`
```

The value of `key2` is the function we need to patch.
We use regex detect if it's source looks like the following.

```js
function(){var a=this.app.Z,b=g.pF()==this.element;if(b&&IE())return new g.Vd(window.outerWidth,window.outerHeight);if(b||a.mi){if(window.matchMedia){a="(width: "+window.innerWidth+"px) and (height: "+window.innerHeight+"px)";this.C&&this.C.media==a||(this.C=window.matchMedia(a));var c=this.C&&this.C.matches}if(c)return new g.Vd(window.innerWidth,window.innerHeight)}else if(this.P&&!this.app.oa)for(a=0;a<this.P.length;a++)if(b=this.P[a],b.query.matches)return new g.Vd(b.size.width,b.size.height);
return new g.Vd(this.element.clientWidth,this.element.clientHeight)};
```

we then call another function that'll update the DOM.


## 2013 May 3

`.watch-playlist-collapsed` and `.watch-medium` now attach to `#player`

```
#watch7-container .watch-playlist
  #player .watch-playlist-collapsed .watch-medium (moved)
    #playlist (Moved to inside #player)
      #watch7-playlist-scrollfloater
        #watch7-playlist-bar
      #watch7-playlist-data
        #watch7-playlist-bar
#watch7-main-container
  ...
```

The following pubsub events fire when you scroll to see the comments since ~2017-02-14.

```
pubsub1 yt-www-pageFrameCssNotifications-load
pubsub1 yt-www-comments-page-updated
```

Something fires on scroll that needs to fire, otherwise the next button doesn't work,
and autoplay doesn't work either.

```
/watch_fragments_ajax
  ?v=9BJ3jDWlOHE
  &list=WL
  &index=15
  &tr=scroll
  &distiller=1
  &ctoken=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%253D
    decode this param with atob(decodeURIComponent(decodeURIComponent("...")))
  &frags=comments
  &spf=load
```


## 2013  April 2

`#watch7-playlist-container` --renamed--> `#playlist`


## 2013 March 20

`#watch7-video-container` --renamed--> `#watch7-container` (renamed back then?)

```
#player (#watch7-playlist-container is injected above this element)
  #player-api
    embed#movie_player
  #watch7-creator-bar
```


## 2013 March ?

```
#watch7-video-container (#watch7-playlist-container is injected above this element)
  #watch7-video
    #watch-player ?
      embed#movie_player ?
```



================================================
FILE: changelog.md
================================================
<h3>Changelog</h3>

## v139 - April 10, 2024

* Fix page top margin as certain elements seem to ignore the CSS properties completely (Issue #88)

## v138 - January 9, 2024

* Bind toggle to `keydown` instead of `keyup` so that pressing `Ctrl+W` to close a tab does not trigger the YTWP toggle when you then focus on a Youtube tab.

## v137 - November 1, 2023

* Bind to `yt-page-data-fetched` and `yt-navigate-finish` to fix the back button not cleaning up the window view since `yt-navigate-start` does not always fire (Issue #72 and #76)
* Bind `keyup` not `keypress` (which is deprecated). Also cancel event during `keydown`. This fixes the `w` key also changing the caption box style. It should also fix changing the toggle key to `Escape` (Issue #71)

## v136 - August 30, 2023

* Attempt to fix `ytd-watch-grid` papercuts (Issue #81)

## v135 - August 30, 2023

* Attempt to fix `ytd-watch-grid` (Issue #81)

## v134 - August 22, 2023

* Fix video container getting shifted again after YT update caused by new `full-bleed-player` layout. Thanks again @Vamael for the fix. (Issue #79)

## v133 - August 18, 2023

* Fix video container getting shifted after YT update caused by new `full-bleed-player` layout. Thanks @Vamael for the fix. (Issue #79)

## v132 - June 29, 2023

* Fix video container getting shifted after YT update (Issue #77)
* Fix nav moving around when guide is open.
* Added `background-color: black` to `#movie_player` so it looks better in light mode.

## 131 - March 11, 2023

* Fix theater mode toggle. `ytd-watch-flexy` DOM is weird. (Issue #75)
* Listen for `yt-navigate-start` and `yt-navigate-finish` events.

## 130 - April 19, 2022

* Add quick boolean toggle for enableOnLoad (Issue #67 and #69)
* Fix video cropping caused by object-fit:cover (Issue #70)
* Make it easy to change script toggle keybinding as it'll need to change (Issue #71)

## 129 - March 9, 2022

* Fix toggling theater mode as YouTube moved the button into the settings cog menu (Issue #66)

## 128 - December 25, 2021

* Disable script when an unavailable video is detected
* Remove some logging

## 127 - April 5, 2021

* Resize the video faster by styling the `#player-wrap` element.

## 126 - April 5, 2021

* Fix scrollbar not being hidden in Chrome.

## 125 - May 5, 2020

* Bind `w` key to toggle off script on current page.
* Prep toggle code for firefox extension.

## 124 - November 6, 2019

* Fix autogenerated gaming channel "live channels" page like https://www.youtube.com/channel/UCZtmNrG53nmbq-Ww2VJrxEQ/live (Issue #46)

## 123 - June 24, 2019

* Support `/user/channelName/live` url paths like https://www.youtube.com/user/pokemon/live (Issue #29)

## 122 - January 30, 2019

* Fix hidden video bug when fullscreen (Issue #43)

## 121 - November 18, 2018

* Fix miniplayer video getting positioned offscreen.

## 120 - November 13, 2018

* Add experimental support for hiding scrollbar in Firefox v63. Go to `about:config` and set `layout.css.scrollbar-width.enabled` to `true`, then restart Firefox.

## 119 - August 22, 2018

* Fix the current video thumbnail not showing up when autoplay is disabled.
* Fix the black bg showing a white section when the miniplayer is active.

## 118 - May 19, 2018

* Support (one of) the new "flexy" youtube interface.

## 117 - April 21, 2018

* Slightly fix the playlist area positioning in the old youtube layout.

## 116 - April 19, 2018

* Use a 32px icon so that it looks better in various browser extensions.
* Support YouTube's experimental MiniPlayer Bar.
* Fix onScroll event not triggering in firefox.

## 115 - December 8, 2017

* Fix script not loading error when the page has only loaded halfway.

## 114 - December 8, 2017

* Use !important to fix compatibility with Youtube+ on the old Youtube layout.

## 113 - December 5, 2017

* Fix the autocomplete popup when the video is still visible.

## 112 - December 2, 2017

* Fix the positioning of the search box's autocomplete popup (it was previously hidden).
* Attempt to cleanup the player every 2.5sec instead of every 1sec, as well as the first 150 frames on page load.

## 111 - November 10, 2017

* Constantly attempt to enter Theater mode every second if we don't enter it right away.
* Support entering theater mode in the old layout.

## 110 - October 6, 2017

* Focus on video on page load.
* Support Youtube+'s successor script (Iridium)'s "Video always visible" feature.

## 109 - September 19, 2017

* Fix seekbar resizing when the window is less than ___px wide.
* Fix scrolling jitter on load caused by the search box getting focus.

## 108 - September 12, 2017

* Toggle theater mode to fix the progressbar since it works consistently.

## 107 - August 30, 2017

* Fix videos on channel pages when first visiting a video page.

## 106 - July 4, 2017

* Enable script on `/c/ChannelName/live` and `/channel/ChannelId/live` pages.

## 105 - June 28, 2017

* Fix update loop not starting.

## 104 - June 27, 2017

* Don't start another fix loop when one is in progress.

## 103 - June 27, 2017

* Reattempt fix 10 more times on page load (shit solution but it works).

## 102 - June 18, 2017

* Fix regex checks in FF v54.
* Attempt to fix resizing the progressbar after a few vidoes have played.
* Fix detection for video -> video page changes.
* Keep track of the player size instead of querying the element every time it's looked up (which is a lot).

## 101 - May 11, 2017

* Finish the last regex for applying the control bar fix on page load, control bar should now work in firefox.

## 100 - May 11, 2017

* Patch the player with a newer method to retrieve the app instance. Works for Chrome, but firefox needs one more regex update. Will push a final fix for firefox later today.

## 99 - May 10, 2017

* Undo the update for the control bar since it can cause a second instance of the player.

## 98 - May 8, 2017

* Quick update for the control bar monkey patch. We need to reinit the player so it's slightly slower than normal. Unfortunately the list of players isn't exposed anymore.

## 97 - May 8, 2017

* Fix the info card button in the top right. Example of button: https://www.youtube.com/watch?v=XGu-WCyiaEY
* Make it easy to edit the script to set the player to a fixed height.

## 96 - April 25, 2017

* Fix Material UI bug. Don't use pubsub anymore since Material UI keeps fucking around with it's API. Just use a periodic timer.

## 95 - April 16, 2017

* TempFix for detecting page transition for the Material UI. Check the URL every 500ms and see if it's changed. A proper fix will come when I find a better solution.

## 94 - April 15, 2017

* Fix high CPU usage caused by binding listeners over and over due to an error (and my bad code).

## 93 - April 4, 2017

* Don't run on `/shared` pages anymore.

## 92 - March 21, 2017

* Fix content positioning in the Material Design css.
* Fix some error spam caused by the pubsub/pubsub2 subscribe() function getting moved.

## 91 - March 2, 2017

* Update CSS to support new beta of the Material Design layout (tested by adding `&f6=4` to the `PREFS` cookie).

## 90 - February 12, 2017

* Support `/shared` pages.

## 89 - January 24, 2017

* Hide the scrollbar on video pages (webkit browsers).
* No longer promote Stylish to hide scrollbars now that the extension spies on you by default.

## 88 - October 25, 2016

* Add support for the Material Design UI experiment.

## 87 - September 3, 2016

* Rewrite the previous fix since it caused problems.

## 86 - September 3, 2016

* Fix empty space when closing the share widget.

## 85 - July 14, 2016

* Fix seekbar fix regex.

## 84 - July 7, 2016

* Don't run script in youtube.com video iframes, or iframes on youtube.com. Now compatible with "Simple YouTube MP3 Button".
* Fix videos on channel pages when first visiting a video url.

## 83 - Mar 27, 2016

* Force width to 100% on the `#player-api` element to fix compatibility with Youtube+.

## 82 - Mar 1, 2016

* Prevent script from running on channel pages.

## 81 - Feb 20, 2016

* Proper fix for the player ui not resizing before being clicked.

## 80 - Feb 20, 2016

* Tempfix the player ui not resizing before being clicked.

## 79 - Feb 16, 2016

* Tempfix the player ui not resizing before being clicked.
* Stop duplicating the stylesheet every page.
* Target `body[data-spf-name="watch"]` if spf is enabled so the player remains the same size when changing video.

## 78 - Jan 18, 2016

* Fix a few errors.

## 77 - Dec 24, 2015

* Fix the autoplay UI not being shown.

## 76 - Dec 24, 2015

* Cleanup cached varibles when changing pages. Should fix the seekbar width breaking after a few videos.
* Make compatible with Youtube+'s "Player always visible when reading comments" feature.

## 75 - Dec 19, 2015

* Trigger resizing the player controls after patching it's size function.

## 74 - Dec 17, 2015

* Fix the Skip Ad UI getting hidden.

## 73 - Dec 13, 2015

* Reenable the html5 seekbar fix since apparently the problem is unrelated to my script.

## 72 - Dec 12, 2015

* Disable the html5 seekbar fix (for now). My technique appears to break everything (comment loading/autoplay/buttons) on occasion.
* Fix playlist widget overlaying sidebar.

## 71 - Nov 24, 2015

* Fix html5 seekbar.

## 70 - Aug 19, 2015

* Fix playlist overlaying the rest of the sidebar.
* Fix playlist overlaying the video description when using Youtube+.

## 69 - July 26, 2015

* Make script slightly compatible with Youtube+ after clicking another video.

## 68 - June 19, 2015

* Update HTML5 fix for the old player. `Objects.keys(obj.constructor.prototype)` was skipping the property, so used `for (var k in obj){}`.

## 67 - June 17, 2015

* Make script slightly compatible with Youtube+

## 66 - June 14, 2015

* Fix player offset when the window is really small.

## 65 - May 28, 2015

* Update HTML5 fix for old player.

## 64 - May 7, 2015

* Fix removing transition on the masthead. YT Center has another rule with `!important`.
* Fix the playlist widget getting hidden beneath the player.

## 63 - May 6, 2015

* Update HTML5 fix.
* Remove transition on the masthead.

## 62 - May 6, 2015

* Fix the height on new `.html5-video-container` element.

## 61 - Apr 30, 2015

* Update HTML5 fix.

## 60 - Apr 29, 2015

* Prevent offset on `.player-api` when in theater mode.

## 59 - Apr 29, 2015

* Update HTML5 fix regexes.

## 58 - Apr 29, 2015

* Hide the `#placeholder-player` element.

## 57 - Mar 16, 2015

* Update HTML5 fix regexes.

## 56 - Mar 2, 2015

* Update HTML5 fix regexes.

## 55 - Feb 24, 2015

* Update HTML5 fix regexes.

## 54 - Feb 23, 2015

* Fix double audio bug after clicking a video on the homepage/search page.
* No longer reloading the html5 player to get the `playerInstance`. We are instead creating an unused dummy `playerInstance` to get the reference to it's constructor, which has a static list of the list of active `playerInstances`.
* Reattempt to subscribe to `pubsub` events 1 second later if we get an error.

## 53 - Feb 12, 2015

* Fix double audio due to not doing a null check.
* Hide `Skip navigation` text that overlays the video.

## 52 - Jan 28, 2015

* Search with regex for function that need replacing in HTML5 player.

## 1.51 - Jan 27, 2015

* Update HTML5 fix variables and check in case things have changed.

## 1.50 - Jan 24, 2015

* New HTML5 player fix method which should fix any weird video => video navigation bugs.

## 1.49 - Jan 9, 2015

* Update to the new "detailpage" variable for the HTML5 fix.

## 1.48 - Dec 20, 2014

* Update to the new "detailpage" variable for the HTML5 fix.

## 1.47 - Dec 11, 2014

* Fix bug when visiting a non /watch page first before navigation to the watch video page.
* Update to the new "detailpage" variable for the HTML5 fix.

## 1.46 - Nov 15, 2014

* Remote undoing the HTML5 player fix before navigating to a new video as it isn't needed.

## 1.45 - Nov 12, 2014

* Re fix the progress bar scaling issue.
* Undo the HTML5 player fix before navigating to a new video in order to also load the video description / comments.

## 1.44 - Oct 31, 2014

* Fix a second video player getting loaded when running this script along Youtube Center, this reintroduces the progressbar bug for users with YT Center. Please use the [dev build of YT Center](https://github.com/YePpHa/YouTubeCenter/raw/master/dist/YouTubeCenter.user.js) until the author pushes the fix to the main build.

## 1.43 - Oct 30, 2014

* Fix HTML5 progress bar not resizing. Thanks to [YePpHa](https://github.com/YePpHa/) for re-solving this bug in YoutubeCenter [Issue #1083](https://github.com/YePpHa/YouTubeCenter/issues/1083).
* Completely hide the Player controls on the HTML5 player since we're reloading the player anyways.

## 1.42 - Aug 18, 2014

* Fix HTML5 progress bar not resizing. Thanks to [YePpHa](https://github.com/YePpHa/) for solving this bug in YoutubeCenter. [[Screenshot](https://i.imgur.com/FcLISVq.png)]
* Fix the player getting right aligned in some cases. [[Screenshot]](https://greasyfork.org/forum/uploads/FileUpload/95/4d455197513c65d1aa243a0d800133.jpg)
* Prevent the script from running twice on the same page.

## 1.41 - Aug 11, 2014

* Remove poorly done HTML5 fix. The HTML5 progress bar will remain unfixed until a Youtube update provides the ability to resize it.
* Use CSS absolutly positioning to move the player. This should fix playback restarting while moving the player.

## 1.40 - July 23, 2014

* Attempt to fix the html5 player. The seek bar & annotations might not scale properly.

## 1.39 - July 12, 2014

* Remove debugging code that broke the script due to a raise in javascript execution security.

## 1.38 - June 17, 2014

* Style `#watch7-sidebar {top: 0 !important; }` to fix the sidebar overlapping the player.
* Fix the guide from being off position when viewing the video.

<p>
  <h4>1.37 - May 13, 2014</h4>
  <ul>
    <li>Style the new <code>#player-mole-container</code> element. It had a height of 0, which was hiding the player.</li>
  </ul>
</p>

<p>
  <h4>1.36 - March 22, 2014</h4>
  <ul>
    <li>[<a href="https://github.com/YePpHa/YouTubeCenter/issues/349">Link</a>] BugFix: On the HTML5 player, resizing it to a non standard width will cause the cursor in the seek bar to not line up. In order to fix this, the script now removes the <code>.watch-small</code>, <code>.watch-medium</code> or <code>.watch-large</code> from the <code>#player</code> element.</li>
  </ul>
</p>

<p>
  <h4>1.35 - Febuary 12, 2014</h4>
  <ul>
    <li>Hook into the <code>appbar-guide-delay-load</code> event. It should be called on every single page however, unlike the other events...</li>
    <li>Fix another regression from rewriting the script: check if the script is on a <code>/watch?</code> page before runnning.</li>
  </ul>
</p>

<p>
  <h4>1.34 - Febuary 7, 2014</h4>
  <ul>
    <li>Re add code to move the playlist as not all users might have updated to the new UI.</li>
  </ul>
</p>

<p>
  <h4>1.33 - Febuary 7, 2014</h4>
  <ul>
    <li>Check the previous player state before moving to decide to autoplay or not.</li>
  </ul>
</p>

<p>
  <h4>1.32 - Febuary 7, 2014</h4>
  <ul>
    <li>Fix issue where video would bug when playing videoes in a row.</li>
    <li>Refactored script.</li>
    <li>Autoplay videos as moving the player pauses the video.</li>
  </ul>
</p>

<p>
  <h4>1.31 - October 28, 2013</h4>
  <ul>
    <li>Automatically uncheck relevant YT Center settings for the user. This is done during the <code>player-added</code> event simply because it (should) be after YT Center is up and running.</li>
  </ul>
</p>

<p>
  <h4>1.30 - October 28, 2013</h4>
  <ul>
    <li>Create a placeholder to mark where the player was, so we can move it back there during a SPF navigation.</li>
    <li>Hook into the <code>init-watch</code> and <code>dispose-watch</code> events rather than the ones used before (<code>player-added</code> and <code>navigate</code>).</li>
  </ul>
</p>

<p>
  <h4>1.29 - October 26, 2013</h4>
  <ul>
    <li>Minor CSS update to fix padding below the playlist tray caused by todays update.</li>
  </ul>
</p>

<p>
  <h4>1.28 - October 23, 2013</h4>
  <ul>
    <li>[<a href="https://userscripts.org/topics/132874">Thread</a>] Update the fixed header so it doesn't overlay the video.</li>
  </ul>
</p>

<p>
  <h4>1.27 - September 8, 2013</h4>
  <ul>
    <li>Go back to moving the #player element rather than #player-api as the playlist bar is no longer attached above it.</li>
  </ul>
</p>

<p>
  <h4>1.26 - August 20, 2013</h4>
  <ul>
    <li>Remove references to <code>-legacy</code>.</li>
    <li>Check the <code>window.location.href</code> for <code>/watch?</code> to run the script. The old way no longer works (checking for <code>#player-api</code>) as it's now pregenerated even on the homepage.</li>
    <li>Add debugging ouput to the console.</li>
    <li>Move the Video Manager bar into <code>#watch7-content</code> so that it fits in seemlessly [<a href="http://i.imgur.com/OqiVBkg.png">Screenshot</a>].</li>
  </ul>
</p>

<p>
  <h4>1.25 - August 15, 2013</h4>
  <ul>
    <li>The script now moves the playlist bar and tray. The playlist tray is moved into the sidebar element.</li>
    <li>General cleanup of unused styling.</li>
    <li>Don't remove the script selector from the body element during AJAX navigation as it looks weird if you notice the removal of this scripts styling. Youtube will removes it later (at a proper time) anyways.</li>
    <li>Only hide the horizontal scrollbar when fully scrolled to the top.</li>
  </ul>
</p>

<p>
  <h4>1.24 - August 15, 2013</h4>
  <ul>
    <li>[<a href="https://userscripts.org/topics/129717">Thread</a>] Update for today's Youtube update. <code>#player-api</code> → <code>#player-api-legacy</code>.</li>
  </ul>
</p>

<p>
  <h4>1.23 - August 11, 2013</h4>
  <ul>
    <li>[<a href="https://userscripts.org/topics/129562">Thread</a>] Bug Fix for users using Youtube Center. Had to override the height on the <code>#player</code> element.</li>
  </ul>
</p>

<p>
  <h4>1.22 - August 10, 2013</h4>
  <ul>
    <li>[<a href="https://userscripts.org/topics/129495">Thread</a>] Bug Fix for users using Firefox. The <code>#player-api</code> element had a <code>float: left;</code> on it. The UI in general doesn't seem to have had the update Chrome does (no fixed header + guide).</li>
  </ul>
</p>

<p>
  <h4>1.21 - August 1, 2013</h4>
  <ul>
    <li>[<a href="https://userscripts.org/topics/129111">Thread</a>] Wrap an exception caused by the <code>window.yt</code> not yet existing when the script gets run in NinjaKit on Safari. Will possibly cause <a href="https://userscripts.org/topics/128760">this bug</a> to resurface when using safari.</li>
  </ul>
</p>

<p>
  <h4>1.20 - July 30, 2013</h4>
  <ul>
    <li>Fix <a href="http://userscripts.org/topics/129094">bug</a> in Firefox/Greasemonkey where the script would break trying to get the <code>window.yt</code> object reference by changing all references to <code>window</code> to <code>unsafeWindow</code>.</li>
  </ul>
</p>

<p>
  <h4>1.19 - July 30, 2013</h4>
  <ul>
    <li>Run the script slightly earlier at the <code>player-added</code> event.</li>
    <li>The horizontal scrollbar is now hidden until the video is no longer visible.</li>
    <li>Fix bug where the playlist tray was overlapping the video.</li>
    <li>Fix bug where the script was run twice on page load.</li>
  </ul>
</p>

<p>
  <h4>1.18 - July 28, 2013</h4>
  <ul>
    <li>
      I managed to find a proper place to hook into Youtube's new AJAX technique. Wrapping <code>window.history.pushState</code> didn't seem to work. On a further look, it also seems like I should have tried wrapping <code>replaceState</code> as well. Instead of wrapping <code>ytspf.config</code> like Youtube Center, I've found <code>yt.pubsub.instance_.subscribe(eventName, callback)</code>. The bugs listed in 1.17 are fixed.
      <ul>
        <li>Listen to the <code>navigate</code> event which is triggered before the page loads through AJAX in order to perform a cleanup (delete the video player as it's out of position).</li>
        <li>Listen to the <code>player-ready</code> event in order to move the player.</li>
      </ul>
    </li>
  </ul>
</p>


<p>
  <h4>1.17 - July 26, 2013</h4>
  Youtube's latest update now loads new pages through ajax (and also when you click a Youtube link in Google).
  <ul>
    <li>Temporarily move the main selector used to identify the script <code>body.ytwp-window-player</code> to <code>html.ytwp-window-player body</code>. Navigating to a new page through ajax will clear all classes attached to the body element.</li>
  </ul>

  Until I've managed to hook into Youtube's new SPF/Ajax technique, the following bugs will be prevalent.
  <ul>
    <li>Visiting the homepage, then clicking a video won't cause the script to run.</li>
    <li>Visiting the homepage (or any other url) will still show the last video above the page.</li>
  </ul>
</p>

<p>
  <h4>1.16 - July 24, 2013</h4>
  <ul>
    <li>Use unsafeWindow.addEventListener(...) instead of window.onresize = function(){...}. window.addEventListener was broken in the recent version of Tampermonkey, but should work now.</li>
  </ul>
</p>

<p>
  <h4>1.15 - July 19, 2013</h4>
  <ul>
    <li>Use absolute positioning on the guide until the user has scrolled past the video completely.</li>
    <li>Do checks for if the video is in view (for switching to the fixed header) when the window is resized.</li>
  </ul>
</p>

<p>
  <h4>1.14 - July 16, 2013</h4>
  <ul>
    <li>Minor refactor on the last update and removed a debugging <code>console.log()</code>.</li>
  </ul>
</p>

<p>
  <h4>1.13 - July 16, 2013</h4>
  <ul>
    <li>Use absolute positioning on the fixed header until the user has scrolled past the video completely. It will add the class <code>ytwp-viewing-video</code> to the body element when doing so.</li>
  </ul>
</p>

<p>
  <h4>1.12 - July 15, 2013</h4>
  <ul>
    <li>Remove some whitespace from some large areas of whitespace caused by branded pages (<a href="http://i.imgur.com/Re06imh.jpg">Example</a>).</li>
    <li>Resize the playlist tray to the same width as the sidebar.</li>
    <li>Inject the completed stylesheet instead of updating as the script runs.</li>
  </ul>
</p>

<p>
  <h4>1.11 - May 7, 2013</h4>
  <ul>
    <li>Fix edge case missed in the last version. There was another rule that affected the padding-left when the guide was collapsed and under the small page width media query.</li>
  </ul>
</p>

<p>
  <h4>1.10 - May 7, 2013</h4>
  <ul>
    <li>Fix padding on the playlist bar when using 'Center Page' in YT Center.</li>
  </ul>
</p>

<p>
  <h4>1.9 - May 3, 2013</h4>
  <ul>
    <li>Removed <code>padding</code> and <code>margin-top</code> override on <code>#player</code>.</li>
    <li>Adjusted selectors for the sidebar due to the shifting of element/classes.</li>
  </ul>
</p>

<p>
  <h4>1.8 - Apr 2, 2013</h4>
  <ul>
    <li>Change all occurance of <code>#playlist-main-container</code> to <code>#playlist</code>.</li>
    <li>Use <code>!important</code> when settings <code>margin-top</code> on the sidebar due to it being set at element level (only on non-playlist pages).</li>
    <li>Fix styling margins on the sidebar on pages with the playlist bar.</li>
  </ul>
</p>

<p>
  <h4>1.7 - Mar 20, 2013</h4>
  <ul>
    <li>Updated for Youtube's new layout. <code>#watch7-video-container</code> became <code>#player</code>, <code>#watch7-video</code> became <code>#player-api</code>.</li>
    <li>The fixed Feedback button code was removed (no longer there).</li>
    <li>Raised the <code>z-index</code> of the <code>#watch7-creator-bar</code> due to the <code>#guide</code> overlaying it and making the buttons unclickable. This is most likely a side effect of the last patch because the <code>#watch7-creator-bar</code> was a child of <code>#watch7-video-container</code> and therafor was no longer moved with the video (speculation). The creator bar currently looks <a href="http://i.imgur.com/rMqaVpy.png">like so</a>.</li>
  </ul>
</p>

<p>
  <h4>1.6 - Feb 28, 2013</h4>
  <ul>
    <li>Script is now only run on the /watch page.</li>
    <li>Removed whitespace margin leftover from moving the video.</li>
    <li>The script now moves the <code>#watch7-video</code> instead of the <code>#watch7-video-container</code> element due to Youtube's new update which will move the <code>#watch7-playlist-container</code> element above the <code>#watch7-video-container</code> element. An example of this new bug can be seen <a href="http://i.imgur.com/pqyuduU.png">here</a>.</li>
    <li>Fixed typo in local variable name.</li>
  </ul>
</p>

<p>
  <h4>1.5 - Feb 5, 2013</h4>
  <ul>
    <li>Refactored code to inject overriding CSS instead of applying styling to the elements themselves.</li>
    <li>Deleted the Feedback element altogether.</li>
    <li>Fixed compatibility with YT Center. (<a href="http://userscripts.org/topics/122305?page=1#posts-480909">Forum Post</a>)</li>
    <li>Fixed styling of the Video Manager bar when browsing your own videos. (<a href="http://userscripts.org/topics/122305?page=1#posts-481046">Forum Post</a>) (<a href="http://i569.photobucket.com/albums/ss134/tom053/window-player-own-video-bug.jpg">Example</a>)</li>
    <li>Added css class to the <code>body</code> tag so people can style around this effects of this script. Use <code>body.ytwp-window-player</code> with your selector(s).</li>
    <li>Overwrote the smooth resizing of the video player.</li>
  </ul>
</p>

<p>
  <h4>1.4 - Jan 6, 2013</h4>
  <ul>
    <li>Fixed the video getting resized when opening the guide (<a href="http://i.imgur.com/V60lu.png">Example</a>).</li>
    <li>Moved the fixed Feedback element to the bottom of the page (<a href="http://i.imgur.com/z5pxM.png">Example</a>).</li>
  </ul>
</p>

<p>
  <h4>1.3 - Dec 27, 2012</h4>
  <ul>
    <li>Fix styling on pages with a playlist bar by:
      <ul>
        <li>Moving down the related videos with the small video player</li>
        <li>Fixing the width of the playlist bar and un-hiding the toggle playlist button in large video mode.</li>
      </ul>
    </li>
    <li>Update script metadata.</li>
  </ul>
</p>

<p>
  <h4>1.2</h4>
  <ul>
    <li>Fixed styling to work in small video mode.</li>
    <li>Fixed styling to work in FireFox. Examples: <a href="http://i.imgur.com/HmR0z.png">[1]</a> | <a href="http://i.imgur.com/LrQR6.png">[2]</a>. <i>Note that the feedback button was moved in later versions.</i></li>
  </ul>
</p>


================================================
FILE: description.md
================================================
# Suggestions

* The `w` key will toggle the script in the current tab.
* Use [Resize Video To Window Size](https://greasyfork.org/en/scripts/10815-resize-video-to-window-size) for Crunchyroll, Vimeo, and a few other sites.

# Screenshots

**After loading the video webpage you will see:**

[![](https://i.imgur.com/GDeEDPA.png)](https://i.imgur.com/GDeEDPA.png)

**It appears above the rest of the site, so you can scroll down for the description, related links, etc.**

[![](https://i.imgur.com/uVDKPUp.jpg)](https://i.imgur.com/uVDKPUp.jpg)

# Changelog

https://github.com/Zren/ResizeYoutubePlayerToWindowSize/blob/master/changelog.md

## v138 - January 9, 2024

* Bind toggle to `keydown` instead of `keyup` so that pressing `Ctrl+W` to close a tab does not trigger the YTWP toggle when you focus on a Youtube tab.

## v137 - November 1, 2023

* Bind to `yt-page-data-fetched` and `yt-navigate-finish` to fix the back button not cleaning up the window view since `yt-navigate-start` does not always fire (Issue #72 and #76)
* Bind `keyup` not `keypress` (which is deprecated). Also cancel event during `keydown`. This fixes the `w` key also changing the caption box style. It should also fix changing the toggle key to `Escape` (Issue #71)

## v139 - April 10, 2024

* Fix page top margin as certain elements seem to ignore the CSS properties completely (Issue #88)


================================================
FILE: ytwp.css
================================================
/*--- Browser Scrollbar */
/* Chrome/Webkit */
body[data-spf-name="watch"],
body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	&::-webkit-scrollbar {
		width: 0 !important;
		height: 0 !important;
	}
}
/* Firefox/Gecko */
/* Requires about:config flag to be toggled as of FireFox v63 */
/* https:/*github.com/Zren/ResizeYoutubePlayerToWindowSize/issues/42 */
html {
	scrollbar-width: none;
}

/*--- Video Player */
body[data-spf-name="watch"],
body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	#player,
	&.ytcenter-site-center.ytcenter-non-resize.ytcenter-guide-visible #player,
	&.ltr.ytcenter-site-center.ytcenter-non-resize.ytcenter-guide-visible.guide-collapsed #player,
	&.ltr.ytcenter-site-center.ytcenter-non-resize.ytcenter-guide-visible.guide-collapsed #player-legacy,
	&.ltr.ytcenter-site-center.ytcenter-non-resize.ytcenter-guide-visible.guide-collapsed #watch7-main-container {
		transition: left 0s linear, padding-left 0s linear;
		padding: 0 !important;
		margin: 0 !important;
	}

	#player-api {
		transition: width 0s linear, left 0s linear;
		/* Bugfix for Firefox */
		/* Parts of the header (search box) are hidden under the player. */
		/* Firefox doesn't seem to be using the fixed header+guide yet. */
		float: initial;
		/* Skinny mode */
		left: 0;
		margin-left: 0;
	}

	/* Theater mode */
	.watch-stage-mode #player .player-api {
		left: initial !important;
		margin-left: initial !important;
	}

	/* Hide the cinema/wide mode button since it's useless. */
	/* #movie_player .ytp-size-button { display: none; } */
}

/* !important is mainly for simplicity, but is needed to override the !important styling when the Guide is open due to: */
/* .sidebar-collapsed #watch7-video, .sidebar-collapsed #watch7-main, .sidebar-collapsed .watch7-playlist { width: 945px!important; } */
/* Also, Youtube Center resizes #player at element level. */
/* Don't resize if Youtube+'s html.floater is detected. */
/* Dont' resize if Youtube+ (Iridium/Material)'s html.iri-always-visible is detected. */
html:not([fullscreen="true"]) body[data-spf-name="watch"] #player,
html:not([fullscreen="true"]) body[data-spf-name="watch"] #player-wrap,
html:not([fullscreen="true"]) body[data-spf-name="watch"] #player-api,
html:not([fullscreen="true"]):not(.floater):not(.iri-always-visible) body[data-spf-name="watch"] #movie_player,
html:not([fullscreen="true"]) body[data-spf-name="watch"] #player-mole-container,
html:not([fullscreen="true"]):not(.floater):not(.iri-always-visible) body[data-spf-name="watch"] .html5-video-container,
html:not([fullscreen="true"]):not(.floater):not(.iri-always-visible) body[data-spf-name="watch"] .html5-main-video,
html:not([fullscreen="true"]) body[data-spf-name="watch"] ytd-watch-flexy[theater] #player-theater-container.ytd-watch-flexy,
html:not([fullscreen="true"]) body[data-spf-name="watch"] ytd-watch-flexy[flexy] #player-container-outer.ytd-watch-flexy,
html:not([fullscreen="true"]) body[data-spf-name="watch"] ytd-watch-flexy[flexy] #player-container-inner.ytd-watch-flexy,
html:not([fullscreen="true"]) body[data-spf-name="watch"] ytd-watch-flexy[flexy] #player-container.ytd-watch-flexy,
html:not([fullscreen="true"]) body[data-spf-name="watch"] ytd-watch-grid[theater] #player-theater-container.ytd-watch-grid,
html:not([fullscreen="true"]) body[data-spf-name="watch"] ytd-watch-grid[flexy] #player-container-outer.ytd-watch-grid,
html:not([fullscreen="true"]) body[data-spf-name="watch"] ytd-watch-grid[flexy] #player-container-inner.ytd-watch-grid,
html:not([fullscreen="true"]) body[data-spf-name="watch"] ytd-watch-grid[flexy] #player-container.ytd-watch-grid,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #player,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #player-wrap,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #player-api,
html:not([fullscreen="true"]):not(.floater):not(.iri-always-visible) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #movie_player,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #player-mole-container,
html:not([fullscreen="true"]):not(.floater):not(.iri-always-visible) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) .html5-video-container,
html:not([fullscreen="true"]):not(.floater):not(.iri-always-visible) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) .html5-main-video,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) ytd-watch-flexy[theater] #player-theater-container.ytd-watch-flexy,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) ytd-watch-flexy[flexy] #player-container-outer.ytd-watch-flexy,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) ytd-watch-flexy[flexy] #player-container-inner.ytd-watch-flexy,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) ytd-watch-flexy[flexy] #player-container.ytd-watch-flexy,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) ytd-watch-grid[theater] #player-theater-container.ytd-watch-grid,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) ytd-watch-grid[flexy] #player-container-outer.ytd-watch-grid,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) ytd-watch-grid[flexy] #player-container-inner.ytd-watch-grid,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) ytd-watch-grid[flexy] #player-container.ytd-watch-grid {
	width: 100% !important;
	min-width: 100% !important;
	max-width: 100% !important;
	height: 100vh !important;
	min-height: 100vh !important;
	max-height: 100vh !important;
}

html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	#player,
	.html5-main-video {
		top: 0 !important;
		right: 0 !important;
		bottom: 0 !important;
		left: 0 !important;
	}
	/* Resize #player-unavailable, #player-api */
	/* Using min/max width/height will keep */
	#player .player-width { width: 100% !important; }
	#player .player-height { height: 100% !important; }

	/* Fix video overlays */
	.html5-video-player .ad-container-single-media-element-annotations, /* Ad */
	.html5-video-player .ytp-upnext { /* Autoplay Next Video */
		top: 0;
	}

	/* Fix video cropping (object-fit: cover) (Issue #70) */
	.ytp-fit-cover-video .html5-main-video {
		object-fit: contain !important;
	}
	/* Thumbnail cropping */
	.ytp-cued-thumbnail-overlay-image {
		background-size: contain !important;
	}

	/*--- Video Container Background */
	#movie_player {
		background-color: #000000;
	}

	/*--- Move Video Player */
	#player {
		position: absolute;
		/* Already top:0; left: 0; */
	}
	& { /* body */
		margin-top: 100vh;
	}

	/* Fix the top right avatar button */
	button.ytp-button.ytp-cards-button {
		top: 0;
	}


	/*--- Sidebar */
	/* Remove the transition delay as you can see it moving on page load. */
	#watch7-sidebar {
		transition: margin-top 0s linear, padding-top 0s linear;
		margin-top: 0 !important;
		top: 0 !important;
	}

	&.cardified-page #watch7-sidebar-contents {
		padding-top: 0;
	}
}

/*--- Absolutely position the fixed header. */
/* Masthead */
#skip-navigation.ytd-masthead {
	top: -150vh; /* Normally -1000px can be shorter than screen (Issue #77) */
}
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	&.hide-header-transition #masthead-positioner {
		transition: top 0s linear !important;
	}
	&.ytwp-viewing-video #masthead-positioner {
		position: absolute;
		top: 100vh !important;
	}
}
/* Lower masthead below Youtube+'s html.floater */
html.floater body[data-spf-name="watch"],
html.floater body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	&.ytwp-viewing-video #masthead-positioner {
		z-index: 5;
	}
}
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	/* Autocomplete popup */
	.sbdd_a {
		top: 56px;
	}
	&.ytwp-viewing-video .sbdd_a {
		top: calc(100vh + 56px) !important;
		position: absolute !important;
	}

	/* Guide */
	/* When watching the video, we need to line it up with the masthead. */
	&.ytwp-viewing-video #appbar-guide-menu {
		display: initial;
		position: absolute;
		top: 100% !important; /* Masthead height */
	}
	&.ytwp-viewing-video #page.watch #guide {
		display: initial;
		margin: 0;
		position: initial;
	}
	/* When the guide is open, it adds body{top:-1000px} which messes with the top position (Issue #77) */
	&.lock-scrollbar {
		top: 0 !important;
		position: static !important;
	}
}

/*--- */
/* MiniPlayer-Bar */
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	#miniplayer-bar #player {
		position: static;
	}
	/* Override inline style (caused by a JS animation) that breaks the miniplayer video */
	/* https://github.com/Zren/ResizeYoutubePlayerToWindowSize/issues/41#issuecomment-439710130 */
	.video-stream.html5-main-video {
		top: 0 !important;
	}
}
html:not([fullscreen="true"]) body[data-spf-name="watch"] #miniplayer-bar #player,
html:not([fullscreen="true"]) body[data-spf-name="watch"] #miniplayer-bar #player-api,
html:not([fullscreen="true"]):not(.floater):not(.iri-always-visible) body[data-spf-name="watch"] #miniplayer-bar #movie_player,
html:not([fullscreen="true"]) body[data-spf-name="watch"] #player-mole-container,
html:not([fullscreen="true"]) body[data-spf-name="watch"]:not(.floater):not(.iri-always-visible) #miniplayer-bar .html5-video-container,
html:not([fullscreen="true"]) body[data-spf-name="watch"]:not(.floater):not(.iri-always-visible) #miniplayer-bar .html5-main-video,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #miniplayer-bar #player,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #miniplayer-bar #player-api,
html:not([fullscreen="true"]):not(.floater):not(.iri-always-visible) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #miniplayer-bar #movie_player,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) #player-mole-container,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player):not(.floater):not(.iri-always-visible) #miniplayer-bar .html5-video-container,
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player):not(.floater):not(.iri-always-visible) #miniplayer-bar .html5-main-video {
	width: 252px !important;
	min-width: 252px !important;
	max-width: 252px !important;
	height: 142px !important;
	min-height: 142px !important;
	max-height: 142px !important;
}

/*--- */
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	/* Hide Scrollbars */
	&.ytwp-scrolltop { overflow-x: hidden; }

	/*--- Fix Other Possible Style Issues */
	#placeholder-player { display: none; }
	#watch-sidebar-spacer { display: none; }
	.skip-nav { display: none; }

	/*--- Whitespace Leftover From Moving The Video */
	#page.watch { padding-top: 0; }
	.player-branded-banner { height: 0; }
}

/*--- Youtube+ Compatiblity */
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	#body-container {
		position: static;
	}
}
html:not([fullscreen="true"]).part_static_size:not(.content-snap-width-skinny-mode) {
	body[data-spf-name="watch"],
	body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
		.watch-non-stage-mode #player-playlist {
			width: 1066px;
		}
	}
}

/*--- */
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	/*--- Playlist Bar */
	#placeholder-playlist,
	#player .player-height#watch-appbar-playlist {
		height: 540px !important;
		max-height: 540px !important;
	}
	#watch-appbar-playlist {
		transition: transform 0s linear;
	}
	#player .player-height#watch-appbar-playlist {
		transform: translateY(0px);
		margin-left: 0;
		top: calc(100vh + 60px);
	}
	.playlist-videos-list {
		max-height: 470px !important;
		height: initial !important;
	}
}


/*--- */
/* Material UI */
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	&.ytwp-scrolltop #extra-buttons {
		display: none !important;
	}
}
/* body > #player:not(.ytd-watch) { display: none; } */
/* body.ytwp-viewing-video #content:not(app-header-layout) ytd-page-manager { margin-top: 0 !important; } */
/* .ytd-watch-0 #content-separator.ytd-watch { margin-top: 0; } */
ytd-app { position: static !important; }
ytd-watch #top { margin-top: 71px !important; }
ytd-watch #container { margin-top: 0 !important; }
ytd-watch #content-separator { margin-top: 0 !important; }

/* Note: Container is now relative since 2023 June (Issue #77) */
/* Note: Container is now a full-bleed-player (Issue #79) */
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	ytd-watch-flexy[theater] #player-wide-container.ytd-watch-flexy,
	ytd-watch-flexy[fullscreen] #player-wide-container.ytd-watch-flexy,
	ytd-watch-flexy[full-bleed-player] #player-full-bleed-container.ytd-watch-flexy, /* Issue #79 (2023-08-17) */
	ytd-watch-flexy[full-bleed-player] #full-bleed-container.ytd-watch-flexy, /* Issue #79 (2023-08-22) */
	ytd-watch-grid[theater] #player-wide-container.ytd-watch-grid,
	ytd-watch-grid[fullscreen] #player-wide-container.ytd-watch-grid,
	ytd-watch-grid[full-bleed-player] #player-full-bleed-container.ytd-watch-grid, /* Issue #81 (2023-08-30) */
	ytd-watch-grid[full-bleed-player] #full-bleed-container.ytd-watch-grid { /* Issue #81 (2023-08-30) */
		position: static;
		height: 0;
		min-height: 0;
	}
	&.ytwp-viewing-video ytd-app #masthead-container.ytd-app {
		position: absolute;
		top: 100vh;
		z-index: 0;
	}
	&.ytwp-viewing-video ytd-watch #masthead-positioner {
		top: 100vh !important;
	}
	.ytp-cued-thumbnail-overlay {
		z-index: 10;
	}
}

/*--- */
html:not([fullscreen="true"]) body[data-spf-name="watch"],
html:not([fullscreen="true"]) body.ytwp-window-player:not(.enhancer-for-youtube-pinned-player) {
	/* Flexy UI */
	ytd-watch-flexy[theater] #player-theater-container.ytd-watch-flexy,
	ytd-watch-grid[theater] #player-theater-container.ytd-watch-grid {
		position: absolute;
		top: 0;
	}
	#error-screen {
		z-index: 11;
	}
}
/* Youtube seems to be ignoring the margin/padding top in certain elements for some reason (Issue #88) */
/* NOT working: ytd-watch-flexy, ytd-watch-grid { padding-top: 71px; } 56px (topnav height) + 15px (margin) */
#page-manager.ytd-app {
	padding-top: var(--ytd-masthead-height,var(--ytd-toolbar-height));
}
Download .txt
gitextract_ufeouyam/

├── 153699.user.js
├── README.md
├── ResizeRedditToWindowSize.user.js
├── ResizeVideoDescription.md
├── ResizeVideoToWindowSize.user.js
├── YTDocs.md
├── changelog.md
├── description.md
└── ytwp.css
Download .txt
SYMBOL INDEX (13 symbols across 2 files)

FILE: 153699.user.js
  function inIframe (line 42) | function inIframe () {
  function isStringType (line 52) | function isStringType(obj) { return typeof obj === 'string'; }
  function isArrayType (line 53) | function isArrayType(obj) { return obj instanceof Array; }
  function isObjectType (line 54) | function isObjectType(obj) { return typeof obj === 'object'; }
  function isUndefined (line 55) | function isUndefined(obj) { return typeof obj === 'undefined'; }
  function buildVenderPropertyDict (line 56) | function buildVenderPropertyDict(propertyNames, value) {
  function observe (line 62) | function observe(selector, config, callback) {
  function prettyHtml (line 202) | function prettyHtml(el) {
  function childOf (line 912) | function childOf(child, ancestor) {
  function cancelIfToggleKey (line 922) | function cancelIfToggleKey(validKeyCallback, e) {

FILE: ResizeVideoToWindowSize.user.js
  function updateHeader (line 128) | function updateHeader() {
  function tick (line 167) | function tick() {
  function onWindowResize (line 302) | function onWindowResize() {
Condensed preview — 9 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (133K chars).
[
  {
    "path": "153699.user.js",
    "chars": 41888,
    "preview": "// ==UserScript==\n// @name            Resize YT To Window Size\n// @description     Moves the YouTube video to the top of"
  },
  {
    "path": "README.md",
    "chars": 530,
    "preview": "# Resize Youtube Player To Window Size\n\nMoves the video to the top of the website and resizes it to the screen size. A s"
  },
  {
    "path": "ResizeRedditToWindowSize.user.js",
    "chars": 3078,
    "preview": "// ==UserScript==\n// @name            Resize Reddit To Window Size\n// @description     Resize the video player for vario"
  },
  {
    "path": "ResizeVideoDescription.md",
    "chars": 1230,
    "preview": "Resizes the following sites\n\n* https://www.crunchyroll.com/\n* https://docs.google.com/file/\n* https://drive.google.com/d"
  },
  {
    "path": "ResizeVideoToWindowSize.user.js",
    "chars": 25132,
    "preview": "// ==UserScript==\n// @name            Resize Video To Window Size\n// @description     Resize the video player for variou"
  },
  {
    "path": "YTDocs.md",
    "chars": 13560,
    "preview": "# Youtube Player Documentation\n\n## 2023 Oct 31\n\nhttps://www.youtube.com/s/desktop/9e7f5697/jsbin/desktop_polymer_enable_"
  },
  {
    "path": "changelog.md",
    "chars": 26459,
    "preview": "<h3>Changelog</h3>\n\n## v139 - April 10, 2024\n\n* Fix page top margin as certain elements seem to ignore the CSS propertie"
  },
  {
    "path": "description.md",
    "chars": 1371,
    "preview": "# Suggestions\n\n* The `w` key will toggle the script in the current tab.\n* Use [Resize Video To Window Size](https://grea"
  },
  {
    "path": "ytwp.css",
    "chars": 15514,
    "preview": "/*--- Browser Scrollbar */\n/* Chrome/Webkit */\nbody[data-spf-name=\"watch\"],\nbody.ytwp-window-player:not(.enhancer-for-yo"
  }
]

About this extraction

This page contains the full source code of the Zren/ResizeYoutubePlayerToWindowSize GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 9 files (125.7 KB), approximately 33.6k tokens, and a symbol index with 13 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!