Allow quick closing of playlists
// ==UserScript==
// @name YouTube Playlist Close
// @version 2.1
// @description Allow quick closing of playlists
// @author AjaxGb
// @match http*://www.youtube.com/*
// @run-at document-start
// @resource buttonDark https://raw.githubusercontent.com/AjaxGb/YouTube-Playlist-Close/master/closeMediumDark.png
// @resource buttonLight https://raw.githubusercontent.com/AjaxGb/YouTube-Playlist-Close/master/closeMediumLight.png
// @grant GM_getResourceURL
// @noframes
// @namespace https://greasyfork.org/users/85711
// ==/UserScript==
(function() {
'use strict';
function GM_addStyle(css) {
const style = document.getElementById('GM_addStyleBy8626') || (function() {
const style = document.createElement('style');
style.type = 'text/css';
style.id = 'GM_addStyleBy8626';
document.head.appendChild(style);
return style;
})();
const sheet = style.sheet;
sheet.insertRule(css, (sheet.rules || sheet.cssRules || []).length);
}
GM_addStyle(`
#YT-Playlist-Close-By-AjaxGb-Close-Button-1234567890 {
width: 44px;
height: 40px;
position: absolute;
top: 0px;
right: 0px;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
opacity: 0.5;
}`);
GM_addStyle(`
#YT-Playlist-Close-By-AjaxGb-Close-Button-1234567890:hover {
opacity: 0.6;
}`);
GM_addStyle(`
#playlist #YT-Playlist-Close-By-AjaxGb-Close-Button-1234567890 {
background-image: url("${GM_getResourceURL('buttonDark')}");
}`);
GM_addStyle(`
#player-playlist #YT-Playlist-Close-By-AjaxGb-Close-Button-1234567890 {
background-image: url("${GM_getResourceURL('buttonLight')}");
}`);
GM_addStyle(`
#player-playlist .playlist-header, #playlist .header {
position: relative;
}`);
function getQueryArgs(query) {
query = (query || window.location.search).substring(1);
if(!query) return {};
return query.split('&').reduce(function(prev, curr) {
const p = curr.split('=');
prev[decodeURIComponent(p[0])] = p[1] ? decodeURIComponent(p[1]) : p[1];
return prev;
}, {});
}
function setQueryArgs(query) {
if(!query) return;
let search = '';
for(let prop in query){
if(query[prop] === undefined){
search += '&'+encodeURIComponent(prop);
}else{
search += '&'+encodeURIComponent(prop)+'='+encodeURIComponent(query[prop]);
}
}
return '?' + search.substr(1);
}
let q;
const b = document.createElement('a');
b.id = 'YT-Playlist-Close-By-AjaxGb-Close-Button-1234567890';
b.title = 'Close playlist';
function updateURL() {
b.href = location.toString();
q = getQueryArgs(b.search);
delete q.list;
delete q.index;
delete q.t;
b.search = setQueryArgs(q);
}
b.onmouseenter = function() {
updateURL();
};
b.onmouseup = function() {
updateURL();
const t = document.getElementById('movie_player').getCurrentTime()|0;
if (t > 0) {
q.time_continue = t;
b.search = setQueryArgs(q);
setTimeout(resetQuery);
}
};
function resetQuery() {
delete q.time_continue;
b.search = setQueryArgs(q);
}
function addButton(p) {
updateURL();
p.appendChild(b);
}
const observer = new MutationObserver(function(mrs) {
if(document.contains(b)) return;
const playlistHeader = document.querySelector([
'#playlist:not(.ytd-miniplayer) .header',
'#player-playlist .playlist-header',
].join(','));
if (playlistHeader) addButton(playlistHeader);
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
})();