Always video progress bar on ani.gamer.com.tw

Enable progress bar on ani.gamer.com.tw

// ==UserScript==
// @name         Always video progress bar on ani.gamer.com.tw
// @namespace    https://wiki.gslin.org/wiki/Always_video_progress_bar_on_ani.gamer.com.tw
// @version      0.20210508.0
// @description  Enable progress bar on ani.gamer.com.tw
// @author       Gea-Suan Lin <darkkiller@gmail.com>
// @match        https://ani.gamer.com.tw/animeVideo.php*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    let bar = document.createElement('div');
    bar.style = 'background: #000; display: block; height: 5px; margin: 0; padding: 0; position: relative; width: 100%;';

    let loadedbar = document.createElement('div');
    loadedbar.style = 'background: #777; display: block; height: 5px; margin: 0; padding: 0; position: absolute; width: 100%;';
    bar.appendChild(loadedbar);

    let progressbar = document.createElement('div');
    progressbar.style = 'background: #00b4d8; display: block; height: 5px; margin: 0; padding: 0; position: absolute; width: 100%; z-index: 1;';
    bar.appendChild(progressbar);

    let vf = document.querySelector('.videoframe');

    /*
     * Append "bar" element to the correspoding position.
     */
    let ob1 = new window.MutationObserver(() => {
        let vjs = document.querySelector('video-js');
        if (!vjs || !vjs.classList.contains('vjs-playing')) {
            return;
        }

        let v = vf.querySelector('#ani_video_html5_api');
        if (!v) {
            return;
        }

        v.addEventListener('progress', () => {
            loadedbar.style.width = (100 * v.buffered.end(0) / v.duration) + '%';
        });
        v.addEventListener('timeupdate', () => {
            progressbar.style.width = (100 * v.currentTime / v.duration) + '%';
        });

        // Different position in ".fullwindow" mode.
        if (vf.classList.contains('vjs-fullwindow')) {
            vf.after(bar);
        } else {
            vf.appendChild(bar);
        }

        ob1.disconnect();
    });
    ob1.observe(vf, {
        childList: true,
        subtree: true,
    });

    /*
     * Handle pause & resume.
     */
    let ob2 = new window.MutationObserver(() => {
        let vjs = document.querySelector('video-js');
        if (!vjs) {
            return;
        }

        if (vjs.classList.contains('vjs-playing') && vjs.classList.contains('vjs-user-inactive')) {
            bar.style.display = 'block';
        } else {
            bar.style.display = 'none';
        }
    });
    ob2.observe(vf, {
        childList: true,
        subtree: true,
    });
})();