I love singing hymns to praise the Lord and give glory to God. There’s something truly powerful about music that lifts the spirit and helps me feel connected to heaven.
But I found myself getting frustrated when trying to use the church's online music pages. The PDF music viewer is small, hard to read, and you constantly have to scroll to the top if you’re flipping through verses or using it on a smaller screen.
So I had an idea: what if I asked ChatGPT to help me write a Tampermonkey script to enhance it?
🙌 The Result: A Distraction-Free Hymn Reader
What started as a small experiment turned into a genuinely useful enhancement. I now have a beautiful "focus mode" button that:
- Hides the page header, sidebar, and footer
- Enlarges the music canvas to make it easier to read
- Shrinks the audio player so it’s out of the way
- Adds zoom in/out buttons to fine-tune the size
- Adds a big jump-to-top button so I can return to the beginning quickly
Before and After Screenshots
Before
After
💬 Want the Same Thing? Here’s the Prompt I Gave ChatGPT
Paste this into ChatGPT to recreate the full script:
Create a Tampermonkey userscript for this page: https://www.churchofjesuschrist.org/media/music/songs/*
The script should:
- Add a small fixed button in the top-right corner labeled 🎵 to toggle "focus mode"
- When toggled ON, hide:
- `platform-header`
- `body > platform-footer:nth-child(23)`
- Side panel with this selector:
`main#root div.Songs__PageWrapper-sc-164xdnp-3.iiQBOL div.sc-eaUbBy.bKpAaE div.Songs__PageSplitWrapper-sc-164xdnp-1.gAzrrl div.SidePanel__LeftAndRightMargins-sc-1pqfxz7-0.iMVKQX`
- Also shrink the audio player `.Songs__StyledAudioPlayer-sc-164xdnp-4` to 0.7 scale, with `padding: 0` and `top: -23px`
- Resize the canvas elements (`canvas.react-pdf__Page__canvas`) to 70% of the window width, maintaining aspect ratio
- Store original canvas size when first toggled, and restore it when toggled off
- Add ➕ and ➖ buttons to the left of the 🎵 button (visible only in focus mode) that increase/decrease canvas width by 100px, maintaining aspect ratio
- Add a large "⬆️ Jump to Top" button fixed to bottom-right, only visible in focus mode, that scrolls to `top: 300px`
The entire script should be production-ready and wrapped in standard Tampermonkey metadata. Output the full script.
🧪 Just Want the Script? Copy & Paste This
// ==UserScript==
// @name Music Page Focus Toggle (v1.9)
// @namespace http://tampermonkey.net/
// @version 1.9
// @description Toggle distractions, zoom controls, and jump button (shown only in focus mode)
// @match https://www.churchofjesuschrist.org/media/music/songs/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
let isFocused = false;
const canvasData = new Map();
const audioSelector = '.Songs__StyledAudioPlayer-sc-164xdnp-4';
const zoomAmount = 100;
const toggleBtn = document.createElement('button');
toggleBtn.textContent = '🎵';
toggleBtn.title = 'Toggle Focus Mode';
styleButton(toggleBtn, { right: '5px' });
const plusBtn = document.createElement('button');
plusBtn.textContent = '➕';
plusBtn.title = 'Zoom In';
styleButton(plusBtn, { right: '42px', display: 'none' });
const minusBtn = document.createElement('button');
minusBtn.textContent = '➖';
minusBtn.title = 'Zoom Out';
styleButton(minusBtn, { right: '79px', display: 'none' });
const jumpBtn = document.createElement('button');
jumpBtn.textContent = '⬆️ Jump to Top';
jumpBtn.title = 'Scroll to Top + 300px';
styleButton(jumpBtn, {
bottom: '20px',
top: '',
right: '20px',
fontSize: '24px',
padding: '16px 24px',
borderRadius: '8px',
background: '#28a745',
display: 'none'
});
document.body.append(toggleBtn, plusBtn, minusBtn, jumpBtn);
toggleBtn.addEventListener('click', () => {
isFocused = !isFocused;
updateFocusStyles(isFocused);
[plusBtn, minusBtn, jumpBtn].forEach(btn => (btn.style.display = isFocused ? 'inline-block' : 'none'));
});
plusBtn.addEventListener('click', () => adjustCanvasWidthBy(zoomAmount));
minusBtn.addEventListener('click', () => adjustCanvasWidthBy(-zoomAmount));
jumpBtn.addEventListener('click', () => {
window.scrollTo({ top: 300, behavior: 'smooth' });
});
function styleButton(btn, overrides = {}) {
Object.assign(btn.style, {
position: 'fixed',
top: '5px',
zIndex: '10000',
padding: '5px 8px',
fontSize: '14px',
background: '#007BFF',
color: '#fff',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
boxShadow: '0 2px 5px rgba(0, 0, 0, 0.3)',
...overrides
});
}
function updateFocusStyles(focus) {
[
'platform-header',
'body > platform-footer:nth-child(23)',
'main#root div.Songs__PageWrapper-sc-164xdnp-3.iiQBOL div.sc-eaUbBy.bKpAaE div.Songs__PageSplitWrapper-sc-164xdnp-1.gAzrrl div.SidePanel__LeftAndRightMargins-sc-1pqfxz7-0.iMVKQX'
].forEach(selector => {
const el = document.querySelector(selector);
if (el) el.style.display = focus ? 'none' : '';
});
if (focus) {
resizeCanvasTo70();
adjustAudioPlayer();
} else {
restoreOriginalCanvasSize();
resetAudioPlayer();
}
}
function resizeCanvasTo70() {
document.querySelectorAll('canvas.react-pdf__Page__canvas').forEach(canvas => {
if (!canvasData.has(canvas)) {
const rect = canvas.getBoundingClientRect();
canvasData.set(canvas, {
width: rect.width,
height: rect.height
});
}
const aspect = canvas.height / canvas.width;
const newWidth = window.innerWidth * 0.7;
const newHeight = newWidth * aspect;
canvas.style.width = `${newWidth}px`;
canvas.style.height = `${newHeight}px`;
canvas.style.display = 'block';
canvas.style.margin = '0 auto';
});
}
function restoreOriginalCanvasSize() {
document.querySelectorAll('canvas.react-pdf__Page__canvas').forEach(canvas => {
const original = canvasData.get(canvas);
if (original) {
canvas.style.width = `${original.width}px`;
canvas.style.height = `${original.height}px`;
} else {
canvas.style.width = '';
canvas.style.height = '';
}
canvas.style.margin = '';
});
}
function adjustCanvasWidthBy(delta) {
document.querySelectorAll('canvas.react-pdf__Page__canvas').forEach(canvas => {
const curWidth = parseFloat(canvas.style.width || canvas.offsetWidth);
const aspect = canvas.height / canvas.width;
const newWidth = curWidth + delta;
const newHeight = newWidth * aspect;
canvas.style.width = `${newWidth}px`;
canvas.style.height = `${newHeight}px`;
});
}
function adjustAudioPlayer() {
const el = document.querySelector(audioSelector);
if (el) {
el.style.transform = 'scale(0.7)';
el.style.transformOrigin = 'top right';
el.style.padding = '0';
el.style.top = '-23px';
el.style.position = 'relative';
}
}
function resetAudioPlayer() {
const el = document.querySelector(audioSelector);
if (el) {
el.style.transform = '';
el.style.padding = '';
el.style.top = '';
el.style.position = '';
}
}
})();
Now I can enjoy singing praises without distractions — and I hope you can too.