Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save brandonmartinez/f4abd4acf32b29db8fe707e9addb4d46 to your computer and use it in GitHub Desktop.
Save brandonmartinez/f4abd4acf32b29db8fe707e9addb4d46 to your computer and use it in GitHub Desktop.
A user script to copy the contents of an ultimate guitar tab to your clipboard.
// ==UserScript==
// @name Copy Tab to Clipboard
// @namespace https://tabs.ultimate-guitar.com/
// @version 1.1
// @description Adds a button to copy tab to clipboard
// @author Brandon Martinez
// @match https://tabs.ultimate-guitar.com/*
// @require https://code.jquery.com/jquery-3.7.1.slim.min.js
// @grant GM_setClipboard
// ==/UserScript==
/* global jQuery */
var $j = jQuery.noConflict(true);
(function () {
"use strict";
// Utility function to find a parent element by level
function findParentByLevel(element, level) {
let parent = element;
for (let i = 0; i < level; i++) {
if (parent) {
parent = parent.parentElement;
} else {
return null;
}
}
return parent;
}
// Function to copy tab content to clipboard
function copyTabToClipboard() {
const editButton = $j('span:contains("Edit")').parent();
editButton.click();
// Wait for the "Make personal edits" button to appear and click it
setTimeout(() => {
const makePersonalEditsButton = $j(
'span:contains("Make personal edits")'
).parent();
makePersonalEditsButton.click();
// Wait for the popup to appear and extract the needed values
setTimeout(() => {
const artistName = $j('input[name="artist_name"]').val();
const songName = $j('input[name="song_name"]').val();
const $tuning = $j('select[name="tuning"] option:selected');
const tuning = !!$tuning ? $tuning.text() : "";
const tuningText = !!tuning
? tuning === "Standard"
? ""
: `Tuning: ${tuning}\n`
: "";
const $capo = $j('select[name="capo"] option:selected');
let capo = !!$capo ? $capo.text() : "";
capo = capo === "(not selected)" ? "" : capo;
const $tonality = $j('select[name="tonality"] option:selected');
let key = !!$tonality ? $tonality.text() : "";
key = key === "(select)" ? "" : key;
const content = $j('textarea[name="content"]').val();
const tabContent = `${songName}\n${artistName}\nKey: ${key}\n${tuningText}TransposedKey: ?\nCapo: ${capo}\nTime: 4/4\nTempo: XXX\nFlow\n\n\n${content}`;
console.log("copying to clipboard", tabContent);
GM_setClipboard(tabContent);
// Close the popup by clicking the "Cancel" button
const cancelButton = $j('span.KNVWh._sWeD:contains("cancel")').parent();
cancelButton.click();
setTimeout(function () {
editButton.click();
}, 300);
}, 300);
}, 300);
}
// Wait for the page to fully load
$j(window).on("load", () => {
setTimeout(function () {
// Find the toolbar div
const editSpan = $j("span:contains(Edit)");
const toolbar = findParentByLevel(editSpan[0], 4);
// Create the "Copy Tab to Clipboard" button
const copyButton = $j(
'<div class="BnYnj"><button type="button" class="rPQkl mcpNL IxFbd gm3Af lTEpj qOnLe"><span class="KNVWh _sWeD">Copy to Clipboard</span></button></div>'
);
copyButton.on("click", copyTabToClipboard);
// Append the button to the toolbar
$j(toolbar).append(copyButton);
}, 500);
});
})();
@a-galiev
Copy link

What for?

@brandonmartinez
Copy link
Author

@a-galiev moving a playlist from UG to OnSong, was tedious with the number of button clicks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment