Greasy Fork

Youtube: Add to Playlist Icons

Adds icons to the video toolbar which adds to specific playlists with 1 click.

当前为 2016-07-27 提交的版本,查看 最新版本

// ==UserScript==
// @name            Youtube: Add to Playlist Icons
// @namespace       http://xshade.ca
// @version         1
// @description     Adds icons to the video toolbar which adds to specific playlists with 1 click.
// @icon            https://youtube.com/favicon.ico
// @author          Chris H (Zren / Shade)
// @include         http*://*.youtube.com/*
// @include         http*://youtube.com/*
// @include         http*://*.youtu.be/*
// @include         http*://youtu.be/*
// @grant           GM_addStyle
// ==/UserScript==


(function (window) {
    //--- Settings
    // name is case sensitive
    var addToPlaylistButtons = [
        { name: "Saved", label: "♥" },
        { name: "Music", label: "♫" },
        { name: "Watch Later", label: "⌚" },
    ];
    
    //---
    var el = function(html) {
        var e = document.createElement('div');
        e.innerHTML = html;
        return e.removeChild(e.firstChild);
    }

    var isWatchUrl = function(url) {
        if (!url)
            url = document.location.href;
        return url.match(/https?:\/\/(www\.)?youtube.com\/watch\?/);
    }
    
    function waitFor(selector, callback) {
        var tick = function(){
            var e = document.querySelector(selector);
            if (e) {
                callback(e);
            } else {
                setTimeout(tick, 100);
            }
        };
        tick();
    }
    
    //---
    var YoutubeScript = function(name) {
        this.name = name;
        this.pubsubListeners = {};
        this.pubsubListeners['init-watch'] = this.checkIfWatchPage.bind(this);
        this.pubsubListeners['appbar-guide-delay-load'] = this.checkIfWatchPage.bind(this);
        
    }
    YoutubeScript.prototype.registerYoutubePubSubListeners = function() {
        for (var eventName in this.pubsubListeners) {
            var eventListener = this.pubsubListeners[eventName];
            window.yt.pubsub.instance_.subscribe(eventName, eventListener);
        }
    }
    YoutubeScript.prototype.checkIfWatchPage = function() {
        console.log('checkIfWatchPage');
        if (isWatchUrl())
            this.onWatchPage();
    }
    YoutubeScript.prototype.onWatchPage = function() {}


    //---
    var ytScript = new YoutubeScript('ytplaylisticons');
    ytScript.onWatchPage = function() {
        this.injectUI();
    }

    ytScript.injectUI = function() {
        var resizeButton = document.querySelector('.ytp-size-button.ytp-button');
        if (resizeButton) {
            for (var i = 0; i < addToPlaylistButtons.length; i++) {
                var playlistData = addToPlaylistButtons[i];
                var button = document.querySelector('.yt-playlist-enqueue-button[data-playlist-name="' + playlistData.name + '"].ytp-button');
                if (!button) {
                    button = el('<button class="yt-playlist-enqueue-button ytp-button" data-playlist-name="' + playlistData.name + '" title="Add to ' + playlistData.name + ' Playlist" style="vertical-align: top; text-align: center;">');
                    button.appendChild(el('<span style="font-size: 24px; font-weight: bold;">' + playlistData.label + '</span>'));
                    button.addEventListener('click', this.addToPlaylist(playlistData.name));
                    resizeButton.parentNode.insertBefore(button, resizeButton);
                    //console.log('addToPlaylistButton', playlistData, button);
                }
            }
        }
        resizeButton.style.display = 'none';
    }
    
    ytScript.addToPlaylist = function(playlistName) {
        return function() {
            document.querySelector('button.addto-button').click();
            waitFor('li.addto-playlist-item[data-item-name="' + playlistName + '"] button.playlist-status', function(e) {
                e.parentNode.click();
            });
        };
    }
    
    ytScript.main = function() {
        try {
            this.registerYoutubePubSubListeners();
        } catch(e) {
            console.error("Could not hook yt.pubsub", e);
            setTimeout(ytScript.main, 1000);
        }
        this.checkIfWatchPage();
    };
    ytScript.main();
    
    var style = ".ytwp-viewing-video #appbar-main-guide-notification-container { top: -110px; }";
    GM_addStyle(style);
    
})(typeof unsafeWindow !== 'undefined' ? unsafeWindow : window);