I really liked your script Here's the code, converted to vanilla JavaScript and removing jQuery dependencies: (function() { 'use strict';
var getVideoTitle = GM_getValue("getVideoTitle", true); var getVideoChannel = GM_getValue("getVideoChannel", false); var getVideoURL = GM_getValue("getVideoURL", false); var videoListSeperator = GM_getValue("videoListSeperator", "|:|");
var listCreationAllowed = true; var urlAtLastCheck = "";
// Function to add a global style without jQuery function addGlobalStyle(css) { var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; style.appendChild(document.createTextNode(css)); head.appendChild(style); }
// Insert CSS for the export button and list display addGlobalStyle(` tp-yt-paper-listbox#items { overflow-x: hidden; }
// Check for playlist URLs and insert the export button setInterval(function() { if (urlAtLastCheck !== window.location.href) { urlAtLastCheck = window.location.href; if (urlAtLastCheck.includes("/playlist?list=")) { InsertButtonASAP(); } } }, 100);
// Function to insert the export button function InsertButtonASAP() { let buttonInsertInterval = setInterval(function() { // Wait for the space for the button to be available if (!document.querySelector("#exportPlainTextList") && document.querySelector("tp-yt-paper-listbox#items")) { const itemsListbox = document.querySelector("tp-yt-paper-listbox#items"); const exportButton = document.createElement("div"); exportButton.id = "exportPlainTextList"; exportButton.innerHTML = `
listCreationAllowed = false; const exportButton = document.querySelector("#exportPlainTextList"); const message = document.createElement("p"); message.id = "listBuildMessage"; message.style.color = "red"; message.style.fontSize = "1.33em"; message.textContent = "Getting list... please click out of the popup to continue autoscrolling..."; exportButton.after(message);
let scrollInterval = setInterval(function() { if (document.querySelector("ytd-continuation-item-renderer.ytd-playlist-video-list-renderer")) { window.scrollTo(0, document.body.scrollHeight); } else { message.remove(); DisplayListOptions(); clearInterval(scrollInterval); } }, 100); }
// Function to display options for list generation function DisplayListOptions() { const body = document.querySelector("body"); const listContainer = document.createElement("div"); listContainer.id = "listDisplayContainer"; listContainer.innerHTML = `
Playlist in plain text X
Get titles
Get channel names
Get URLs
Name/Author/URL seperator
Get list
`; body.appendChild(listContainer);
// Add event listeners for options and list generation const getVideoTitleCheckbox = document.getElementById("getVideoTitleCB"); getVideoTitleCheckbox.addEventListener("change", function() { getVideoTitle = this.checked; GM_setValue("getVideoTitle", getVideoTitle); });
// Function to build and display the playlist text function BuildAndDisplayList() { const listOptionsContainer = document.getElementById("listDisplayOptions"); listOptionsContainer.style.display = "none"; const listTextarea = document.querySelector("#listDisplayContainer > textarea"); listTextarea.style.display = "block";
let videoTitleArr = []; let videoChannelArr = []; let videoURLArr = []; let videoCount = 0;
// Loop through each video in the playlist for (const item of videoListItems) { if (getVideoTitle) { videoTitleArr.push(item.querySelector("#video-title").getAttribute("title")); }
if (getVideoURL) { videoURLArr.push("https://www.youtube.com" + item.querySelector("#video-title").getAttribute("href").split("&")[0]); }
if (getVideoChannel) { videoChannelArr.push(item.querySelector("#channel-name yt-formatted-string.ytd-channel-name > a").textContent); }
videoCount++; }
// Build the playlist text let list = ""; for (let i = 0; i < videoCount; i++) { if (getVideoTitle) { list += videoTitleArr[i] + " "; }
if (getVideoChannel) { list += (getVideoTitle ? videoListSeperator : "") + videoChannelArr[i]; }
if (getVideoURL) { list += (getVideoTitle || getVideoChannel ? videoListSeperator : "") + videoURLArr[i]; }
list += "\n"; }
// Display the playlist text in the textarea listTextarea.value = list; } })();
I really liked your script Here's the code, converted to vanilla JavaScript and removing jQuery dependencies: (function() {
'use strict';
var getVideoTitle = GM_getValue("getVideoTitle", true);
var getVideoChannel = GM_getValue("getVideoChannel", false);
var getVideoURL = GM_getValue("getVideoURL", false);
var videoListSeperator = GM_getValue("videoListSeperator", "|:|");
var listCreationAllowed = true;
var urlAtLastCheck = "";
// Function to add a global style without jQuery
function addGlobalStyle(css) {
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(css));
head.appendChild(style);
}
// Insert CSS for the export button and list display
addGlobalStyle(`
tp-yt-paper-listbox#items { overflow-x: hidden; }
#exportPlainTextList {
cursor: pointer;
height: 36px;
width: 100%;
display: flex;
align-items: center;
}
#exportPlainTextList > img {
height: 24px; width: 24px;
color: rgb(144, 144, 144);
padding: 0 13px 0 16px;
filter: contrast(0%);
}
#exportPlainTextList > span {
font-family: "Roboto","Arial",sans-serif;
color: var(--yt-spec-text-primary);
white-space: nowrap;
font-size: 1.4rem;
line-height: 2rem;
font-weight: 400;
}
#exportPlainTextList:hover { background-color: rgba(255,255,255,0.1); }
ytd-menu-popup-renderer.ytd-popup-container { overflow-x: hidden !important; max-height: none !important; }
#listDisplayContainer {
position: fixed;
z-index: 9999;
margin: 0 auto;
background-color: #464646;
padding: 10px;
border-radius: 5px;
left: 0;
right: 0;
max-width: 100vw;
width: 1200px;
height: 900px;
max-height: 90vh;
top: 5vh;
resize: both;
overflow: hidden;
}
#listDisplayContainer > textarea {
box-sizing: border-box;
width: 100%;
margin: 10px 0;
height: calc(100% - 40px);
background-color: #262626;
border: none;
color: #EEE;
border-radius: 5px;
resize: none;
}
#closeTheListThing {
float: right;
font-weight: bold;
background-color: RGBA(255,255,255,0.25);
border: none;
font-size: 17px;
border-radius: 10px;
height: 25px;
width: 25px;
cursor: pointer;
}
#closeTheListThing:hover { background-color: rgba(255,255,255,0.5); }
`);
// Check for playlist URLs and insert the export button
setInterval(function() {
if (urlAtLastCheck !== window.location.href) {
urlAtLastCheck = window.location.href;
if (urlAtLastCheck.includes("/playlist?list=")) {
InsertButtonASAP();
}
}
}, 100);
// Function to insert the export button
function InsertButtonASAP() {
let buttonInsertInterval = setInterval(function() {
// Wait for the space for the button to be available
if (!document.querySelector("#exportPlainTextList") && document.querySelector("tp-yt-paper-listbox#items")) {
const itemsListbox = document.querySelector("tp-yt-paper-listbox#items");
const exportButton = document.createElement("div");
exportButton.id = "exportPlainTextList";
exportButton.innerHTML = `
Export Playlist
`;
itemsListbox.appendChild(exportButton);
exportButton.addEventListener("click", ScrollUntillAllVisible);
setTimeout(function() { clearInterval(buttonInsertInterval); }, 5000);
}
}, 100);
}
// Function to scroll the playlist until all videos are visible
function ScrollUntillAllVisible() {
if (!listCreationAllowed) {
return;
}
document.querySelector("ytd-browse[page-subtype='playlist']").click();
listCreationAllowed = false;
const exportButton = document.querySelector("#exportPlainTextList");
const message = document.createElement("p");
message.id = "listBuildMessage";
message.style.color = "red";
message.style.fontSize = "1.33em";
message.textContent = "Getting list...
please click out of the popup to continue autoscrolling...";
exportButton.after(message);
let scrollInterval = setInterval(function() {
if (document.querySelector("ytd-continuation-item-renderer.ytd-playlist-video-list-renderer")) {
window.scrollTo(0, document.body.scrollHeight);
} else {
message.remove();
DisplayListOptions();
clearInterval(scrollInterval);
}
}, 100);
}
// Function to display options for list generation
function DisplayListOptions() {
const body = document.querySelector("body");
const listContainer = document.createElement("div");
listContainer.id = "listDisplayContainer";
listContainer.innerHTML = `
Playlist in plain text
X
`;
body.appendChild(listContainer);
// Add event listeners for options and list generation
const getVideoTitleCheckbox = document.getElementById("getVideoTitleCB");
getVideoTitleCheckbox.addEventListener("change", function() {
getVideoTitle = this.checked;
GM_setValue("getVideoTitle", getVideoTitle);
});
const getVideoChannelCheckbox = document.getElementById("getVideoChannelCB");
getVideoChannelCheckbox.addEventListener("change", function() {
getVideoChannel = this.checked;
GM_setValue("getVideoChannel", getVideoChannel);
});
const getVideoURLCheckbox = document.getElementById("getVideoURLCB");
getVideoURLCheckbox.addEventListener("change", function() {
getVideoURL = this.checked;
GM_setValue("getVideoURL", getVideoURL);
});
const videoListSeperatorInput = document.getElementById("videoListSeperatorInput");
videoListSeperatorInput.addEventListener("change", function() {
videoListSeperator = this.value;
GM_setValue("videoListSeperator", videoListSeperator);
});
const getListButton = document.getElementById("listDisplayGetListButton");
getListButton.addEventListener("click", BuildAndDisplayList);
const closeButton = document.getElementById("closeTheListThing");
closeButton.addEventListener("click", function() {
listContainer.remove();
listCreationAllowed = true;
});
}
// Function to build and display the playlist text
function BuildAndDisplayList() {
const listOptionsContainer = document.getElementById("listDisplayOptions");
listOptionsContainer.style.display = "none";
const listTextarea = document.querySelector("#listDisplayContainer > textarea");
listTextarea.style.display = "block";
let videoTitleArr = [];
let videoChannelArr = [];
let videoURLArr = [];
let videoCount = 0;
const videoListItems = document.querySelectorAll("ytd-playlist-video-list-renderer > #contents.ytd-playlist-video-list-renderer > ytd-playlist-video-renderer #content");
// Loop through each video in the playlist
for (const item of videoListItems) {
if (getVideoTitle) {
videoTitleArr.push(item.querySelector("#video-title").getAttribute("title"));
}
if (getVideoURL) {
videoURLArr.push("https://www.youtube.com" + item.querySelector("#video-title").getAttribute("href").split("&")[0]);
}
if (getVideoChannel) {
videoChannelArr.push(item.querySelector("#channel-name yt-formatted-string.ytd-channel-name > a").textContent);
}
videoCount++;
}
// Build the playlist text
let list = "";
for (let i = 0; i < videoCount; i++) {
if (getVideoTitle) {
list += videoTitleArr[i] + " ";
}
if (getVideoChannel) {
list += (getVideoTitle ? videoListSeperator : "") + videoChannelArr[i];
}
if (getVideoURL) {
list += (getVideoTitle || getVideoChannel ? videoListSeperator : "") + videoURLArr[i];
}
list += "\n";
}
// Display the playlist text in the textarea
listTextarea.value = list;
}
})();