Skip to content

Instantly share code, notes, and snippets.

@TheChilliPL
Last active April 27, 2022 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TheChilliPL/d4b8225a3b6a1087b80735c167130e28 to your computer and use it in GitHub Desktop.
Save TheChilliPL/d4b8225a3b6a1087b80735c167130e28 to your computer and use it in GitHub Desktop.
VocaloidLyrics.fandom.com lyrics copier
(() => {
let romajiHeader = Array.from(document.querySelectorAll(":is(td,th)")).filter(e => e.textContent.trim() == "Romaji")[0];
let table = romajiHeader.parentNode.parentNode;
let isThead = table.tagName == "THEAD";
if(!isThead) {
table = table.parentNode.getElementsByTagName("TBODY")[0];
}
let rows = Array.from(table.children);
let columnCount = rows[0].children.length;
let output = Array.from(Array(columnCount), ()=>[]);
for(let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
let row = rows[rowIndex];
for(let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
let column = row.children[columnIndex] ?? row.children[0];
let columnText = (column?.innerText?.trim() ?? "") + "\n";
output[columnIndex].push(columnText);
}
}
let dialog = document.createElement("DIALOG");
dialog.style.resize = "vertical";
dialog.style.display = "flex";
dialog.style.flexDirection = "column";
dialog.style.height = "60vh";
dialog.style.minHeight = "200px";
document.body.append(dialog);
let h1 = document.createElement("H1");
h1.textContent = "Lyrics copier";
dialog.append(h1);
let h2 = document.createElement("H2");
let authorLink = document.createElement("A");
authorLink.href = "https://github.com/TheChilliPL";
authorLink.textContent = "Chilli!"
h2.append("by ", authorLink);
dialog.append(h2);
let container = document.createElement("DIV");
container.style.display = "flex";
container.style.flexGrow = "1";
let textareas = [];
let syncScroll = true;
let ignoreScrollEvents = 0;
for(let column of output) {
let textarea = document.createElement("TEXTAREA");
textarea.textContent = column.join("");
textarea.style.resize = "horizontal";
textarea.style.minWidth = "100px";
textarea.style.whiteSpace = "pre";
textarea.style.lineHeight = "1.2";
textarea.readOnly = true;
textarea.addEventListener("resize", console.debug);
textarea.addEventListener("scroll", () => {
if (!syncScroll) return;
if (ignoreScrollEvents) {
ignoreScrollEvents--;
return;
}
let scroll = textarea.scrollTop;
for (let area of textareas) {
if (area != textarea) {
ignoreScrollEvents++;
area.scrollTop = scroll;
}
}
});
container.append(textarea);
textareas.push(textarea);
}
dialog.append(container);
let hint = document.createElement("P");
hint.style.fontSize = "80%";
hint.style.opacity = "0.8";
let hintLink = document.createElement("A");
hintLink.href = "https://gist.github.com/TheChilliPL/d4b8225a3b6a1087b80735c167130e28";
hintLink.textContent = "See the source on GitHub.";
hint.append(
"You can select and copy text from each column now.",
document.createElement("BR"),
hintLink
);
dialog.append(hint);
let syncCheckboxLabel = document.createElement("LABEL");
let syncCheckbox = document.createElement("INPUT");
syncCheckbox.type = "checkbox";
syncCheckbox.checked = true;
syncCheckbox.addEventListener("change", () => {
let checked = syncCheckbox.checked;
if (checked) {
let averageScroll = textareas.map(area => area.scrollTop).reduce((a, b) => a + b) / textareas.length;
textareas.forEach(area => area.scrollTop = averageScroll);
}
syncScroll = checked;
});
syncCheckboxLabel.append(syncCheckbox, "Synchronize scroll position");
dialog.append(syncCheckboxLabel);
let form = document.createElement("FORM");
form.method = "dialog";
dialog.append(form);
let button = document.createElement("BUTTON");
button.textContent = "Close modal [Esc]";
button.style.width = "100%";
form.append(button);
dialog.addEventListener("close", () => {
dialog.remove();
});
dialog.showModal();
return output;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment