Quantcast
Channel: Active questions tagged youtube-api - Stack Overflow
Viewing all articles
Browse latest Browse all 3831

YouTube old mini-player extension scroll issues

$
0
0

I have been using this mini-player YouTube extension for a while. It's not on the Chrome Store anymore, but I have a folder of it from the developer.

The developer isn't working on this anymore, so I am asking here. I like this extension, but I have been having this issue whenever I open a YouTube link externally. It throws off the YouTube player when scrolling. It's not the biggest issue in the world, but I am just seeing if there is something that can be done to fix it. I am not a big coder, so I am asking here. I am not sure if this can be fixed or its something conflicting with new YouTube since this extension is pretty old. I pasted some links with the full code and some pictures.

https://imgur.com/a/tAi84xP

https://pastebin.com/7nBrFhrk

"use strict";(function() {    let DOCK_DOCKED = 'docked', DOCK_FLOATING = 'floating';    let PAGE_CHANNEL = 'channel', PAGE_HOME = 'home', PAGE_SEARCH = 'search', PAGE_SUBSCRIPTIONS = 'subscriptions', PAGE_WATCH = 'watch';    let SCREEN_PADDING = 16;    let currentAnimation, currentAnimationCancelled, currentDockMode, currentVideoId, currentPage;    let queryParams, isNewPage;    let screen, screenHeader, screenTitle, screenButtonClose, screenButtonMove, screenButtonResizeTopLeft, screenButtonResizeTopRight, screenButtonResizeBottomLeft, screenButtonResizeBottomRight, isScreenMove, isScreenResize;    let iframe, iframeVideo, moviePlayer, moviePlayerObserver = new MutationObserver(onMoviePlayerObserve), playerAPI, video, videoTitle;    let intervalCurrentTime, intervalIframeInitialize, intervalVideoInitialize;    let localStorage = window.localStorage['rjgtav.youtube-mini-player'] ? JSON.parse(window.localStorage['rjgtav.youtube-mini-player']) : {};    // Thanks to https://www.reddit.com/user/roombascj    // Workaround: Chrome doesn't fire 'resize' event when it adds the scrollbar    // Source: https://pastebin.com/tgDxgPza    let windowResizeListener = document.createElement('iframe');    windowResizeListener.id = 'rj-resize-listener';    windowResizeListener.onload = () => windowResizeListener.contentWindow.addEventListener('resize', onWindowResize);    window.addEventListener('scroll', onWindowScroll);    document.addEventListener('DOMContentLoaded', onPageLoad);    document.addEventListener('spfdone', onPageLoad);    // #YoutubeMaterialDesign    document.addEventListener('yt-navigate-finish', onPageLoad);    document.addEventListener('yt-update-title', onPageTitle);    function initializeIframe () {        if (iframe != null) return;        screen = document.createElement('div');        screen.id = 'rj-miniplayer-screen';        screen.style.position = 'fixed';        document.body.appendChild(screen);        screenHeader = document.createElement('div');        screenHeader.className = 'rj-miniplayer-header';        screen.appendChild(screenHeader);        screenButtonMove = document.createElement('div');        screenButtonMove.className = 'rj-miniplayer-move';        screenButtonMove.title = 'Move';        screenButtonMove.style.backgroundImage = "url('" + chrome.extension.getURL('assets/button/move.png') +"')";        screenButtonMove.addEventListener('mousedown', onScreenMouseDown);        screenHeader.appendChild(screenButtonMove);        screenTitle = document.createElement('div');        screenTitle.className = 'rj-miniplayer-title';        screenTitle.addEventListener('click', onScreenTitleClick);        screenHeader.appendChild(screenTitle);        screenButtonClose = document.createElement('div');        screenButtonClose.className = 'rj-miniplayer-close';        screenButtonClose.title = 'Close';        screenButtonClose.style.backgroundImage = "url('" + chrome.extension.getURL('assets/button/close.png') +"')";        screenButtonClose.addEventListener('click', onScreenButtonCloseClick);        screenHeader.appendChild(screenButtonClose);        screenButtonResizeBottomRight = document.createElement('div');        screenButtonResizeBottomRight.className = 'rj-miniplayer-resize bottom-right';        screenButtonResizeBottomRight.title = 'Resize';        screenButtonResizeBottomRight.addEventListener('mousedown', onScreenMouseDown);        screen.appendChild(screenButtonResizeBottomRight);        screenButtonResizeTopRight = document.createElement('div');        screenButtonResizeTopRight.className = 'rj-miniplayer-resize top-right';        screenButtonResizeTopRight.title = 'Resize';        screenButtonResizeTopRight.addEventListener('mousedown', onScreenMouseDown);        screenHeader.appendChild(screenButtonResizeTopRight);        iframe = document.createElement('iframe');        iframe.setAttribute('allowfullscreen', '1');        iframe.setAttribute('frameborder', '0');        iframe.onload = onIframeLoad;        screen.appendChild(iframe);    }    function updateIframeSource () {        if (iframe == null) return;        // If it's the same video, we keep playing it        if (currentVideoId == queryParams.v) return;        currentVideoId = queryParams.v;        iframeVideo = null;        iframe.contentWindow.location.replace('https://www.youtube.com/embed/'+ currentVideoId +'?autoplay=1&modestbranding=1&rel=0&showinfo=0');        // We periodically update the video.currentTime, so the Share button on Youtube works as expected        // Update: this has a high performance impact :/        //clearInterval(intervalCurrentTime);        //intervalCurrentTime = setInterval(() => iframeVideo ? video.currentTime = iframeVideo.currentTime : null, 1000);    }    function initializeVideo() {        if (video != null) {            video.removeEventListener('playing', onVideoPlay);            video.removeEventListener('play', onVideoPlay);            video.removeEventListener('seeking', onVideoSeek);            video.removeEventListener('seeked', onVideoSeek);        }        // Prevent Youtube from auto-playing        // Workaround: we use intervals so this still runs when the tab isn't focused        clearInterval(intervalVideoInitialize);        intervalVideoInitialize = setInterval(() => {            // Hide moviePlayer to increase performance            moviePlayer = document.getElementById('movie_player');            moviePlayerObserver.observe(moviePlayer, { childList: true });            if (moviePlayer == null) return;            playerAPI = moviePlayer.parentNode;            video = playerAPI.getElementsByTagName('video')[0];            if (video == null) return;            video.pause();            video.volume = 0;            video.addEventListener('playing', onVideoPlay);            video.addEventListener('play', onVideoPlay);            video.addEventListener('seeking', onVideoSeek);            video.addEventListener('seeked', onVideoSeek);            clearInterval(intervalVideoInitialize);        }, 25);    }    function _updateScreenState(noAnimation, forceAnimation) {        if (playerAPI == null || screen == null) return;        let dockMode = (currentPage != PAGE_WATCH || window.scrollY > screen.offsetHeight / 2) ? DOCK_FLOATING : DOCK_DOCKED;        // Cancel current animation        if (currentDockMode != dockMode) {            screen.removeEventListener('transitionend', onScreenTransitionEnd);            currentAnimationCancelled = currentAnimation != null;            currentAnimation = null;        }        let positionEnd = _loadScreenState(dockMode), positionStart;        let isAnimating = forceAnimation || currentDockMode != dockMode || currentAnimation != null;        currentDockMode = dockMode;        if (isAnimating) {            // Update animation states            if (currentAnimation == null) {                // Note: updating the height/width causes a stutter/redraw on the iframe. Therefore we do it at the beginning, where it is less noticeable                positionStart = screen.getBoundingClientRect();                screen.style.height = positionEnd.height +'px';                screen.style.width = positionEnd.width +'px';                screen.style.transform = 'scale('+ (positionStart.width / positionEnd.width) +')';            } else {                positionStart = currentAnimation.start;            }            currentAnimation = { end: positionEnd, start: positionStart, onScreenTransitionEnd: currentAnimation ? currentAnimation.onScreenTransitionEnd : null };            if (currentDockMode == DOCK_DOCKED) {                iframe.style.boxShadow = 'initial';            }            // Animate            if (!noAnimation) {                window.requestAnimationFrame(() => window.requestAnimationFrame(() => window.requestAnimationFrame(() => {                    // Abort animation if cancelled                    if (currentAnimation == null)                        return;                    screen.style.transition = '.2s ease-in-out';                    if (currentAnimationCancelled) {                        screen.style.transform = '';                        onScreenTransitionEnd();                    } else {                        screen.style.transform ='translateX('+ (currentAnimation.end.left - currentAnimation.start.left) +'px)'+'translateY('+ (currentAnimation.end.top - currentAnimation.start.top) +'px)';                    }                    // Prevent multiple addEventListener during a single transition (e.g. when scrolling, this method is spammed)                    if (!currentAnimation || !currentAnimation.onScreenTransitionEnd) {                        currentAnimation.onScreenTransitionEnd = onScreenTransitionEnd;                        screen.addEventListener('transitionend', onScreenTransitionEnd);                    }                })));            } else {                onScreenTransitionEnd();            }        } else {            // When the movie is docked at the top of the watch page            screen.style.transition = '';            screen.style.height = positionEnd.height +'px';            screen.style.width = positionEnd.width +'px';            screen.style.top = positionEnd.top +'px';            screen.style.left = positionEnd.left +'px';        }    }    function _updateScreenVisibility(visible) {        if (visible) {            if (moviePlayer) moviePlayer.style.display = 'none';            screen.style.display = 'initial';            _updateScreenState(true);        } else {            if (moviePlayer) moviePlayer.style.display = 'initial';            screen.style.display = 'none';        }    }    function _calculateDefaultScreenState(dockMode) {        let state = {};        state.height = playerAPI.offsetHeight / 2;        state.width = playerAPI.offsetWidth / 2;        // #YoutubeMaterialDesign - when switching to the Home page and such        if (currentPage != PAGE_WATCH && (state.width == 0 || state.height == 0)) {            let backupState = _loadScreenState(DOCK_DOCKED, PAGE_WATCH);            state.height = backupState.height / 2;            state.width = backupState.width / 2;        }        if (currentPage == PAGE_CHANNEL || currentPage == PAGE_HOME || currentPage == PAGE_SUBSCRIPTIONS) {            state.top = (window.innerHeight - state.height - SCREEN_PADDING);            state.left = (window.innerWidth - state.width - SCREEN_PADDING - SCREEN_PADDING);        }        if (currentPage == PAGE_SEARCH) {            state.top = (window.innerHeight - state.height) / 2;            state.left = (window.innerWidth - state.width - SCREEN_PADDING - SCREEN_PADDING);        }        if (currentPage == PAGE_WATCH) {            if (dockMode == DOCK_FLOATING) {                let sidebar = document.getElementById('watch7-sidebar') || document.getElementById('related'); // #YoutubeMaterialDesign                state.top = (window.innerHeight - state.height) / 2;                state.left = (sidebar.getBoundingClientRect().left - (state.width - sidebar.offsetWidth) / 2);            } else {                state = playerAPI.getBoundingClientRect();            }        }        return _saveScreenState(dockMode, state.height, state.width, state.left, state.top);    }    function _loadScreenState(dockMode, page) {        let state = localStorage.screenState = localStorage.screenState || {};            state = state[page || currentPage] = state[page || currentPage] || {};            state = state[dockMode] = state[dockMode] || {};        // Load default state, if none was previously saved        if ((currentPage == PAGE_WATCH && dockMode == DOCK_DOCKED) || state.height == null || state.width == null || state.left == null || state.top == null)            state = _calculateDefaultScreenState(dockMode);        // In case the screen is outside the screen, move it back inside        if (dockMode == DOCK_FLOATING) {            if (state.left + state.width + SCREEN_PADDING > window.innerWidth)                state.left = window.innerWidth - state.width - SCREEN_PADDING;            if (state.left < SCREEN_PADDING)                state.left = SCREEN_PADDING;            if (state.top + state.height + SCREEN_PADDING > window.innerHeight)                state.top = window.innerHeight - state.height - SCREEN_PADDING;            if (state.top < 100)                state.top = 100;        }        return state;    }    function _saveScreenState(dockMode, height, width, left, top) {        let state = localStorage.screenState = localStorage.screenState || {};            state = state[currentPage] = state[currentPage] || {};            state = state[dockMode] = state[dockMode] || {};        // Save to localStorage        state.height = height;        state.width = width;        state.left = left;        state.top = top;        window.localStorage['rjgtav.youtube-mini-player'] = JSON.stringify(localStorage);        return state;    }    function _getBoundingDocumentRect(e) {        var box = e.getBoundingClientRect();        var body = document.body;        var docEl = document.documentElement;        var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;        var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;        var clientTop = docEl.clientTop || body.clientTop || 0;        var clientLeft = docEl.clientLeft || body.clientLeft || 0;        var height = e.offsetHeight;        var width = e.offsetWidth;        var top  = box.top +  scrollTop - clientTop;        var left = box.left + scrollLeft - clientLeft;        return { height, width, top, left };    }    //---------------------------------------------------------------------    // Event Handlers    //---------------------------------------------------------------------    // Thanks to http://stackoverflow.com/questions/34077641/how-to-detect-page-navigation-on-youtube-and-modify-html-before-page-is-rendered    function onPageLoad() {        let isFirstTime = iframe == null;        // Parse query params        queryParams = {};        let params = window.location.search.substring(1).split('&');        params.forEach((param) => {            let pair = param.split('=');            queryParams[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);        })        // Parse current page        currentPage = null;        currentPage = currentPage == null && queryParams.v != null ? PAGE_WATCH : currentPage;        currentPage = currentPage == null && queryParams.search_query != null ? PAGE_SEARCH : currentPage;        currentPage = currentPage == null && window.location.href.indexOf('/channel/') != -1 ? PAGE_CHANNEL : currentPage;        currentPage = currentPage == null && window.location.href.indexOf('/feeed/subscriptions') != -1 ? PAGE_SUBSCRIPTIONS : currentPage;        currentPage = currentPage == null ? PAGE_HOME : currentPage;        if (currentPage == PAGE_WATCH) {            initializeIframe();            initializeVideo();            onPageTitle();            updateIframeSource();            // Make sure the mini player is visible (in case it was hidden by the user)            _updateScreenVisibility(true);        }        document.body.appendChild(windowResizeListener); // Note: we need to append this before the window.onload        window.requestAnimationFrame(() => {            _updateScreenState(isFirstTime, true);        });    }    function onPageTitle(event) {        let index = document.title.indexOf('- YouTube');        if (index > -1)            screenTitle.innerText = document.title.substring(0, index);    }    function onIframeLoad(event) {        // Workaround: we use intervals so this still runs when the tab isn't focused        clearInterval(intervalIframeInitialize);        intervalIframeInitialize = setInterval(() => {            iframeVideo = iframe.contentWindow.document.getElementsByTagName('video')[0];            if (iframeVideo) {                iframeVideo.currentTime = video.currentTime;                iframeVideo.onended = onIframeVideoEnded;                clearInterval(intervalIframeInitialize);            }        }, 25);    }    function onIframeVideoEnded(event) {        if (currentPage != PAGE_WATCH) return;        // In order to trigger Youtube's functionality (e.g. AutoPlay, Playlist), we need to make the original video trigger the 'ended' event        // Therefore, we seek to the end and play it. See #onVideoSeek() for details        video.currentTime = video.duration - 0.25;        _updateScreenVisibility(false);    }    function onScreenButtonCloseClick(event) {        iframeVideo.pause();        _updateScreenVisibility(false);    }    function onScreenMouseDown(event) {        event.preventDefault();        isScreenMove = event.target == screenButtonMove;        isScreenResize = event.target == screenButtonResizeBottomRight || event.target == screenButtonResizeTopRight;        iframe.style.pointerEvents = 'none';        screen.classList.add('dragging');        screenButtonMove.removeEventListener('mousedown', onScreenMouseDown);        screenButtonResizeBottomRight.removeEventListener('mousedown', onScreenMouseDown);        screenButtonResizeTopRight.removeEventListener('mousedown', onScreenMouseDown);        document.body.addEventListener('mouseup', onScreenMouseUp);        document.body.addEventListener('mousemove', onScreenMouseMove);    }    function onScreenMouseUp(event) {        event.preventDefault();        if (isScreenMove) {            // Save            _saveScreenState(currentDockMode, screen.offsetHeight, screen.offsetWidth, screen.offsetLeft, screen.offsetTop);        }        if (isScreenResize) {            var currentSize = screen.getBoundingClientRect();            //screen.style.left =(screen.offsetLeft - (currentSize.width - screen.offsetWidth) / 2) +'px';            //screen.style.top = (screen.offsetTop - (currentSize.height - screen.offsetHeight) / 2) +'px';            screen.style.height = currentSize.height +'px';            screen.style.width = currentSize.width +'px';            screen.style.transform = '';            // Save            _saveScreenState(currentDockMode, currentSize.height, currentSize.width, screen.offsetLeft, screen.offsetTop);        }        isScreenMove = isScreenResize = false;        iframe.style.pointerEvents = 'initial';        screen.classList.remove('dragging');        document.body.removeEventListener('mouseup', onScreenMouseUp);        document.body.removeEventListener('mousemove', onScreenMouseMove);        screenButtonMove.addEventListener('mousedown', onScreenMouseDown);        screenButtonResizeBottomRight.addEventListener('mousedown', onScreenMouseDown);        screenButtonResizeTopRight.addEventListener('mousedown', onScreenMouseDown);    }    function onScreenMouseMove(event) {        event.preventDefault();        if (isScreenMove) {            screen.style.left = Math.min(window.innerWidth - screen.offsetWidth - SCREEN_PADDING, Math.max(SCREEN_PADDING, parseInt(screen.style.left) + event.movementX)) +'px';            screen.style.top = Math.min(window.innerHeight - screen.offsetHeight - SCREEN_PADDING, Math.max(148, parseInt(screen.style.top) + event.movementY)) +'px';        }        if (isScreenResize) {            var currentSize = screen.getBoundingClientRect();            var width = screen.offsetWidth;            var newWidth = currentSize.width + event.movementX;            screen.style.transform = 'scaleX('+ newWidth / width +') scaleY('+ newWidth / width +')';        }    }    function onScreenTitleClick(event) {        var videoUrl = window.location.href.split('&t=')[0];        window.location.href = videoUrl + (iframeVideo ? ('&t='+ parseInt(iframeVideo.currentTime)) : '');    }    function onScreenTransitionEnd(event) {        if (event && event.propertyName != 'transform') return;        screen.removeEventListener('transitionend', onScreenTransitionEnd);        if (currentDockMode == DOCK_FLOATING) {            iframe.style.boxShadow = '0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22)';        }        screen.className = currentDockMode;        screen.style.left = currentAnimation.end.left +'px';        screen.style.top = currentAnimation.end.top +'px';             screen.style.transform = '';        screen.style.transition = '';        currentAnimation = null;        currentAnimationCancelled = false;    }    function onMoviePlayerObserve(mutators) {        if (mutators[0].addedNodes.length > 0)            initializeVideo();    }    function onVideoPlay(event) {        if (video == null) return;        if (!(video.duration > 0 && Math.abs(video.currentTime - video.duration) <= 1)) // See #onIframeVideoEnded() for details            video.pause();    }    function onVideoSeek(event) {        if (video == null) return;        if (video.duration > 0 && Math.abs(video.currentTime - video.duration) <= 1) { // See #onIframeVideoEnded() for details            video.play();        } else {            video.pause();            if (iframeVideo != null)                iframeVideo.currentTime = video.currentTime;            // Make sure the mini player is visible (in case it was hidden by the user)            _updateScreenVisibility(true);        }    }    function onWindowResize() {        window.requestAnimationFrame(() => {            _updateScreenState();        });    }    function onWindowScroll(event) {        _updateScreenState();    }})();

Viewing all articles
Browse latest Browse all 3831

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>