CIJ subtitle scroll into view

make the subtitle in transcript scrolled into viewport

// ==UserScript==
// @name          CIJ subtitle scroll into view
// @namespace     http://tampermonkey.net/
// @version       0.0.2
// @description   make the subtitle in transcript scrolled into viewport
// @author        Sapjax
// @license MIT
// @match         https://cijapanese.com/*
// @icon          https://www.google.com/s2/favicons?sz=64&domain=cijapanese.com
// @grant         none
// @run-at        document-body
// ==/UserScript==


(function() {
    // The selector for the main container.
    const transcriptSelector = '.transcript';
    // The selector for the button inside the container.
    const buttonSelector = '.btn-ghost-yellow';

    /**
 * Scrolls the button into view within its container, without affecting the page scroll.
 * @param {HTMLElement} transcriptElement The scrollable container.
 * @param {HTMLElement} buttonElement The button element to scroll.
 */
    function scrollButtonToTop(transcriptElement, buttonElement) {
        if (transcriptElement && buttonElement) {
            const transcriptRect = transcriptElement.getBoundingClientRect();
            const buttonRect = buttonElement.getBoundingClientRect();
            const scrollMargin = 20

            // Calculate the new scroll position.
            // The scroll position is the button's position relative to the container's top edge,
            // plus the container's current scroll position.
            const newScrollTop = buttonRect.top - transcriptRect.top + transcriptElement.scrollTop - scrollMargin;

            // Smoothly scroll the container to the new position.
            transcriptElement.scrollTo({
                top: newScrollTop,
                behavior: 'smooth'
            });
            console.log("Button element appeared or changed. Scrolling it to the top of the container.");
        }
    }

    /**
 * Creates and starts a MutationObserver to watch the transcript container for changes.
 * This function will be called once the transcript container is found.
 * @param {HTMLElement} transcriptElement The transcript container to observe.
 */
    function observeTranscriptForButtonChanges(transcriptElement) {
        const buttonObserver = new MutationObserver((mutationsList, obs) => {
            // We only need to check for a new button if the DOM structure changed.
            for (const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    const currentButton = transcriptElement.querySelector(buttonSelector);
                    if (currentButton) {
                        scrollButtonToTop(transcriptElement, currentButton);
                        return;
                    }
                }
            }
        });

        const config = {
            childList: true, // Watch for additions and removals of children.
            subtree: true    // Watch all descendants.
        };

        buttonObserver.observe(transcriptElement, config);
        console.log("Started observing the '.transcript' container for button changes.");
    }

    /**
 * Initializes the entire process: checks for the transcript, applies styles,
 * and sets up the observer for the button.
 */
    function initialize() {
        let transcriptElement = document.querySelector(transcriptSelector);

        if (!transcriptElement) {
            // If the transcript element is not yet in the DOM, watch for it.
            const mainObserver = new MutationObserver((mutationsList, obs) => {
                for (const mutation of mutationsList) {
                    if (mutation.type === 'childList') {
                        transcriptElement = document.querySelector(transcriptSelector);
                        if (transcriptElement) {
                            console.log("'.transcript' container has appeared. Applying styles.");
                            transcriptElement.style.height = '200px';
                            transcriptElement.style.overflow = 'auto';

                            const initialButton = transcriptElement.querySelector(buttonSelector);
                            if (initialButton) {
                                scrollButtonToTop(transcriptElement, initialButton);
                            }

                            observeTranscriptForButtonChanges(transcriptElement);
                            return;
                        }
                    }
                }
            });

            mainObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
            console.log("Waiting for '.transcript' container to appear.");

        } else {
            // If the transcript element already exists, apply styles and proceed.
            console.log("'.transcript' container already exists. Applying styles.");
            transcriptElement.style.height = '200px';
            transcriptElement.style.overflow = 'auto';


            observeTranscriptForButtonChanges(transcriptElement);
        }
    }

    // Start the process.
    initialize();

})();