Showtime: enable YouTube-style keyboard controls

Use similar controls as on YouTube when watching Showtime (`f` for full screen, `k` to play/pause, `c` for captions, `m` to mute/unmute, `p` to enable/disable PiP, `j`/`l` to go back/skip 10 seconds, left/right arrows for 5 seconds, `0`..`9` for 0% .. 90%)

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Showtime: enable YouTube-style keyboard controls
// @namespace    showtime.keyboard
// @version      0.4
// @description  Use similar controls as on YouTube when watching Showtime (`f` for full screen, `k` to play/pause, `c` for captions, `m` to mute/unmute, `p` to enable/disable PiP, `j`/`l` to go back/skip 10 seconds, left/right arrows for 5 seconds, `0`..`9` for 0% .. 90%)
// @match        https://showtime.com/*
// @match        https://www.showtime.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // change these constants if you prefer to use a different key
    // (or change the letter to uppercase if you want the shortcut to require the use of Shift)
    const FULL_SCREEN_KEY = 'f';
    const PLAY_PAUSE_KEY = 'k';
    const FORWARDS_TEN_SECONDS_KEY = 'l';
    const BACKWARDS_TEN_SECONDS_KEY = 'j';
    const FORWARDS_FIVE_SECONDS_KEY = 'ArrowRight';
    const BACKWARDS_FIVE_SECONDS_KEY = 'ArrowLeft';
    const CLOSED_CAPTIONS_KEY = 'c';
    const MUTE_UNMUTE_KEY = 'm';
    const PICTURE_IN_PICTURE_KEY = 'p';
    const NUMBER_KEYS_ENABLED = true; // 0 for 0%, 1 for 10%… up to 9 for 90%
    const CODE_ZERO = 48; // keycode for character '0'

    function clickButton(className) {
        const buttons = document.querySelectorAll('button.' + className);
        if (buttons && buttons.length == 1) {
            buttons[0].click();
        } else {
            console.error('Button not found!');
        }
    }

    function isPlaying(videoElement) {
        return !!(videoElement.currentTime > 0 && !videoElement.paused && !videoElement.ended && videoElement.readyState > 2);
    }

    addEventListener("keydown", function(e) {
        if (e.ctrlKey || e.altKey) { // return early if any modifier key like Control or Alt is part of the key press
            return;
        }
        const videos = document.getElementsByTagName('video');
        const video = videos && videos.length == 1 ? videos[0] : null;

        if (e.key == FULL_SCREEN_KEY) {
            clickButton(window.innerHeight == screen.height ? 'exit-fullscreen' : 'enter-fullscreen');
        } else if (e.key == PLAY_PAUSE_KEY) {
            clickButton(video && isPlaying(video) ? 'pause' : 'play');
        } else if (e.key == MUTE_UNMUTE_KEY) {
            clickButton('volume');
        } else if (e.key == PICTURE_IN_PICTURE_KEY) {
            if (document.pictureInPictureElement) {
                document.exitPictureInPicture();
            } else {
                video && video.requestPictureInPicture();
            }
        } else if (e.key == FORWARDS_TEN_SECONDS_KEY && video) {
            video.currentTime += 10;
        } else if (e.key == BACKWARDS_TEN_SECONDS_KEY && video) {
            video.currentTime -= 10;
        } else if (e.key == FORWARDS_FIVE_SECONDS_KEY && video) {
            video.currentTime += 5;
        } else if (e.key == BACKWARDS_FIVE_SECONDS_KEY && video) {
            video.currentTime -= 5;
        } else if (NUMBER_KEYS_ENABLED && e.keyCode >= CODE_ZERO && e.keyCode <= CODE_ZERO + 9) {
            video.currentTime = (e.keyCode - CODE_ZERO) * (video.duration / 10.0);
        } else if (e.key == CLOSED_CAPTIONS_KEY) {
            const ccContainer = document.querySelectorAll('div.player-closed-captioning-container > div');
            if (ccContainer && ccContainer.length == 1) {
                clickButton(ccContainer[0].classList.contains('closed-captioning-enabled') ? 'closed-captioning-disable' : 'closed-captioning-enable');
            } else {
                console.error('No CC container found');
            }
        }
    });
})();