YouTube Watch Later Remove Button on Hover

Show a remove button on hover over video thumbnails in the Watch Later list

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         YouTube Watch Later Remove Button on Hover
// @namespace    http://tampermonkey.net/
// @version      0.6.2
// @description  Show a remove button on hover over video thumbnails in the Watch Later list
// @license MIT
// @match        https://www.youtube.com/*
// @run-at              document-start
// @grant               none
// @inject-into         page
// ==/UserScript==

(function () {
    'use strict';

    let scriptEnable = false;

    const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);

    function getItemData(menu) {
        if (!menu) return;
        let items = ((menu || 0).menuRenderer || 0).items || 0;
        if (!(items.length >= 1)) return;
        const filtered = items.filter((entry) => {
            if (!entry || typeof entry !== 'object') return false;
            try {
                const t = (JSON.stringify(entry) || '');
                return t.includes('ACTION_REMOVE_VIDEO');
            } catch (e) {
                return false;
            }
        });
        if (filtered.length !== 1) return;
        let itemData = filtered[0];
        itemData = Object.values(itemData).filter(e => e.serviceEndpoint || e.command)[0];
        if (!itemData) return;
        return itemData;
    }

    const removeButtonOnclick = function (e) {
        const button = this;
        if (!scriptEnable) return;

        let videoElement = button.closest('ytd-thumbnail');
        if (!videoElement) return;
        let renderer = videoElement.closest('ytd-playlist-video-renderer.style-scope.ytd-playlist-video-list-renderer');
        if (!renderer) return;

        let data = insp(renderer).data || 0;
        const itemData = getItemData(data.menu);
        if (!itemData) return;

        e.preventDefault(); // Prevent the default action of the event
        e.stopPropagation(); // Stop the event from bubbling up
        e.stopImmediatePropagation(); // Prevents other listeners of the same event from being called

        const cntNode = (document.querySelector('ytd-app') || renderer);

        (function (data) {

            const a = data.serviceEndpoint;
            const b = data.command;

            a && this.ytComponentBehavior.resolveCommand(a);
            b && this.ytComponentBehavior.resolveCommand(b);

        }).call(insp(cntNode), itemData);

    };

    function createRemoveButton(videoElement) {
        let removeButton = document.createElement('button');
        removeButton.className = 'watch-later-remove-button';
        removeButton.textContent = 'Remove';
        removeButton.style.position = 'absolute';
        removeButton.style.top = '5px';
        removeButton.style.right = '5px';
        removeButton.style.zIndex = '1000';

        removeButton.onclick = removeButtonOnclick;
        videoElement.appendChild(removeButton);
    }

    const mouseenterHandler = function (e) {
        if (!e || !(e.target instanceof HTMLElement)) return;
        if (!scriptEnable) return;
        if (!e.target.classList.contains('ytd-playlist-video-renderer')) return;
        let videoElement = e.target.closest('ytd-thumbnail');
        if (!videoElement) return;
        let renderer = videoElement.closest('ytd-playlist-video-renderer.style-scope.ytd-playlist-video-list-renderer');
        if (!renderer || renderer.is !== 'ytd-playlist-video-renderer') return;
        let data = insp(renderer).data || 0;
        let itemData = getItemData(data.menu);
        if (!itemData) return;
        let button = videoElement.querySelector('button.watch-later-remove-button')
        if (!button) {
            createRemoveButton(videoElement);
        } else {
            button.style.display = '';
        }
    };

    const mouseleaveHandler = function (e) {
        if (!e || !(e.target instanceof HTMLElement)) return;
        if (!e.target.classList.contains('ytd-playlist-video-renderer')) return;
        let button = e.target.querySelector('button.watch-later-remove-button');
        if (button) {
            button.style.display = 'none';
        }
    };


    document.addEventListener('yt-navigate-finish', () => {

        const newEnable = location.pathname === '/playlist' && location.search.includes('list=WL');

        if (scriptEnable ^ newEnable) {

            if (scriptEnable) {
                scriptEnable = false;
                document.removeEventListener('mouseenter', mouseenterHandler, true);
                document.removeEventListener('mouseleave', mouseleaveHandler, true);
            } else if (newEnable) {
                scriptEnable = true;
                document.addEventListener('mouseenter', mouseenterHandler, true);
                document.addEventListener('mouseleave', mouseleaveHandler, true);
            }

        }

    }, false);

})();