Youtube button to delete a video from a playlist

Adds a button to directly remove videos from the playlist on YouTube

< Feedback on Youtube button to delete a video from a playlist

Review: OK - script works, but has bugs

§
Posted: 2025-04-10
Edited: 2025-04-10

Didn't work as of this review, but fixed it by replacing the removeButton variable with the following selector.

const removeButton = document.querySelector('[d="M11 17H9V8h2v9zm4-9h-2v9h2V8zm4-4v1h-1v16H6V5H5V4h4V3h6v1h4zm-2 1H7v15h10V5z"]').closest('[role="menuitem"]');

It is selecting the rubbish bin SVG path and searching the parent nodes up to the menu item.

The rest of the scripts works fine, I just have to go slow. If the pop up in the lower left corner says "sorry, something went wrong" the video was not removed. Now to clear 1000+ videos from a PocketTube playlist!

§
Posted: 2025-04-10

added a lock variable to prevent deletions until the pop up notifying the outcome appears.

// ==UserScript==
// @name      Youtube button to delete a video from a playlist
// @name:en   Youtube button to delete a video from a playlist
// @namespace    http://tampermonkey.net/
// @version      1.533
// @description:en  Adds a button to directly remove videos from the playlist on YouTube
// @description  Добавляет кнопку для удаления видео из плейлиста на ютубе
// @author       You
// @match        https://www.youtube.com/*
// @grant        none
// @license      MIT
// @downloadURL https://update.greasyfork.org/scripts/499379/Youtube%20button%20to%20delete%20a%20video%20from%20a%20playlist.user.js
// @updateURL https://update.greasyfork.org/scripts/499379/Youtube%20button%20to%20delete%20a%20video%20from%20a%20playlist.meta.js
// ==/UserScript==

(function () {
    'use strict';

    console.log('Script started');

    var lock = false;

    const style = document.createElement('style');
    style.textContent = `
        .remove-button {
            display: flex;
            align-items: center;
            border: none;
            background: transparent;
            color: #909090;
            cursor: pointer;
            margin-top: 5px;
            padding: 0;
            transition: color 0.3s, filter 0.3s, transform 0.3s;
            font-size: 20px; /* Установите размер текста для иконки */
        }

        .remove-button:hover {
            color: #b0b0b0; /* Светлее цвет для эффекта наводки */
            filter: brightness(1.3); /* Сделать кнопку немного светлее */
        }

        .remove-button:active {
            transform: scale(0.82); /* Уменьшение кнопки при нажатии */
        }
    `;
    document.head.append(style);

    function addRemoveButton(video) {
        console.log('Adding remove button');
        if (!video.querySelector('.remove-button')) {
            const button = document.createElement('button');
            button.classList.add('remove-button');

            const trashIcon = document.createElement('span');
            trashIcon.textContent = '🗑️'; // Unicode character for trash can

            button.appendChild(trashIcon);

            button.addEventListener('click', async () => {
                if (lock) { console.info('Wait for last action to complete before attempting this action.'); return; } else { lock = true; }

                video.querySelector('#button').click();

                await new Promise(resolve => setTimeout(resolve, 20)); // wait 500ms

                const removeButton = document.querySelector('[d="M11 17H9V8h2v9zm4-9h-2v9h2V8zm4-4v1h-1v16H6V5H5V4h4V3h6v1h4zm-2 1H7v15h10V5z"]').closest('[role="menuitem"]');
                let removed = false;

                if (removeButton) {
                    removeButton.click();
                    removed = true;
                }

                if (!removed) {
                    lock = false;
                    alert('It was not possible to delete the video. Please try again.');

                }
            });

            video.querySelector('#meta').appendChild(button);
        }
    }

    function addRemoveButtons() {
        console.log('Adding remove buttons to all videos');
        const videoContainers = document.querySelectorAll('ytd-playlist-video-renderer');
        console.log('Found', videoContainers.length, 'videos');
        videoContainers.forEach(addRemoveButton);
    }

    function init() {
        console.log('Initializing script');
        addRemoveButtons();

        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1 && node.matches('ytd-playlist-video-renderer')) {
                        addRemoveButton(node);
                    }
                });
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });
        const popupObserver = new MutationObserver((mutationList, observer) => {
            //release lock
            for (const mutation of mutationList) {
                console.debug(mutation);
                if (mutation.addedNodes[0].textContent.includes('Sorry, something went wrong.')) {
                    alert('Something went wrong wehn removing the video. Please try again.');
                } else { lock = false; }
            }
        });
        popupObserver.observe(
            document.querySelector("body > ytd-app > ytd-popup-container"),
            { childList: true }
        );

        window.addEventListener('yt-navigate-finish', addRemoveButtons);
    }

    init();
})();

Post reply

Sign in to post a reply.