Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ivanca/a90848f8ee4d7f62e939630013e214d8 to your computer and use it in GitHub Desktop.
Save Ivanca/a90848f8ee4d7f62e939630013e214d8 to your computer and use it in GitHub Desktop.
Userscript: Rewind Commands For Ultimate-guitar Web Player
// ==UserScript==
// @name Rewind Commands For Ultimate-guitar Web Player
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Use Enter Key to Rewind, twice for current section, great to use with a USB Pedal
// @author Ivan Castellanos
// @match https://tabs.ultimate-guitar.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=ultimate-guitar.com
// @grant none
// ==/UserScript==
(function() {
'use strict';
function isPlaying() {
const buttons = getPlayerButtons();
return getComputedStyle(buttons[2]).background.startsWith('rgb(68, 219, 94)');
}
function getPlayerButtons() {
return [...document.querySelectorAll('article > div > section button')].filter(
e => window.innerHeight - e.getBoundingClientRect().top < 100
);
}
function simulateClick(element, x = 0, y = 0) {
const clickEvent = new MouseEvent('click', {
currentTarget: element,
view: window,
bubbles: true,
cancelable: true,
clientX: x,
clientY: y,
nativeEvent: {
clientX: x,
clientY: y
}
});
element.dispatchEvent(clickEvent);
}
let timeoutId = null;
function handleKeypress(e) {
if (e.key !== 'Enter') {
return;
}
if (timeoutId == null) {
timeoutId = setTimeout(() => {
restartFromSelection();
timeoutId = null;
}, 600);
} else {
goToStartOfCurrentPart();
clearTimeout(timeoutId);
timeoutId = null;
}
}
function restartFromSelection() {
const [, restartBtn, playBtn] = getPlayerButtons();
const playing = isPlaying()
simulateClick(restartBtn);
simulateClick(playBtn);
if (playing) {
// This is because we need to pause then unpause to get the coundown feature to work
setTimeout(e => simulateClick(playBtn), 10);
}
}
function goToStartOfCurrentPart() {
const playing = isPlaying();
const playButton = getPlayerButtons()[2];
const playHead = document.querySelector('.XXwY0');
const headOffset = parseFloat(playHead.style.transform.replace(/[^\d.]+/g, ''));
const headOffsetAsPercent = headOffset / playHead.parentElement.offsetWidth * 100;
const allParts = [...document.querySelectorAll('.XCWM7')];
const clientRect = playHead.parentElement.getBoundingClientRect();
let clickOffsetPercent = 0;
for (let index = 0; index < allParts.length; index++) {
const nextPartOffset = clickOffsetPercent + parseFloat(allParts[index].style.width);
if (nextPartOffset > headOffsetAsPercent) {
break;
}
clickOffsetPercent = nextPartOffset;
}
let clientXClick = playHead.parentElement.offsetWidth * clickOffsetPercent / 100 + clientRect.left;
let clientYClick = clientRect.top + 1;
simulateClick(playHead.parentElement, clientXClick, clientYClick);
simulateClick(playButton);
if (playing) {
// This is because we need to pause then unpause to get the coundown feature to work
setTimeout(() => simulateClick(playButton), 10);
}
}
document.addEventListener('keypress', handleKeypress);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment