- // ==UserScript==
- // @name Disable YouTube Hotkeys with Modern Settings Page
- // @namespace http://tampermonkey.net/
- // @version 1.4
- // @description Disable various YouTube hotkeys, including frame skip, with a modern settings page
- // @author You
- // @match *://www.youtube.com/*
- // @grant GM_registerMenuCommand
- // @grant GM_setValue
- // @grant GM_getValue
- // @grant GM_addStyle
- // @license MIT
- // ==/UserScript==
-
-
- (function() {
- 'use strict';
-
- // Load saved settings or default to enabling all keys
- let settings = GM_getValue('hotkeySettings', {
- disableNumericKeys: false,
- disableSpacebar: false,
- disableArrowKeys: false,
- disableFKey: false,
- disableMKey: false,
- disableSpeedControl: false,
- disableFrameSkip: false
- });
-
- // Function to handle keydown events and disable selected hotkeys
- window.addEventListener('keydown', function(e) {
- // Disable numeric keys (0-9)
- if (settings.disableNumericKeys && e.key >= '0' && e.key <= '9') {
- e.stopPropagation();
- e.preventDefault();
- }
-
- // Disable spacebar
- if (settings.disableSpacebar && e.code === 'Space') {
- e.stopPropagation();
- e.preventDefault();
- }
-
- // Disable arrow keys (left, right, up, down)
- if (settings.disableArrowKeys && ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.code)) {
- e.stopPropagation();
- e.preventDefault();
- }
-
- // Disable F (for fullscreen)
- if (settings.disableFKey && e.key.toLowerCase() === 'f') {
- e.stopPropagation();
- e.preventDefault();
- }
-
- // Disable M (for mute)
- if (settings.disableMKey && e.key.toLowerCase() === 'm') {
- e.stopPropagation();
- e.preventDefault();
- }
-
- // Disable speed control (Shift + > or Shift + <)
- if (settings.disableSpeedControl && (e.shiftKey && (e.key === '>' || e.key === '<'))) {
- e.stopPropagation();
- e.preventDefault();
- }
-
- // Disable frame skip (`,` for backward, `.` for forward)
- if (settings.disableFrameSkip && (e.key === ',' || e.key === '.')) {
- e.stopPropagation();
- e.preventDefault();
- }
- }, true);
-
- // Create and display the settings modal using safe DOM manipulation
- function openSettings() {
- // Remove any existing modal or overlay
- let existingModal = document.getElementById('yt-hotkey-settings-modal');
- let existingOverlay = document.getElementById('yt-hotkey-settings-overlay');
- if (existingModal) existingModal.remove();
- if (existingOverlay) existingOverlay.remove();
-
- // Create the modal container
- let modal = document.createElement('div');
- modal.id = 'yt-hotkey-settings-modal';
- modal.className = 'modal-card';
-
- // Create modal header
- let header = document.createElement('div');
- header.className = 'modal-header';
-
- let title = document.createElement('h2');
- title.textContent = 'YouTube Hotkey Settings';
- header.appendChild(title);
-
- let closeButton = document.createElement('span');
- closeButton.id = 'closeSettingsBtn';
- closeButton.className = 'close-btn';
- closeButton.textContent = '×';
- header.appendChild(closeButton);
-
- modal.appendChild(header);
-
- // Create modal content (checkboxes)
- let content = document.createElement('div');
- content.className = 'modal-content';
-
- let checkboxes = [
- { id: 'disableNumericKeys', label: 'Disable Numeric Keys (0-9)', checked: settings.disableNumericKeys },
- { id: 'disableSpacebar', label: 'Disable Spacebar (Play/Pause)', checked: settings.disableSpacebar },
- { id: 'disableArrowKeys', label: 'Disable Arrow Keys (Rewind/FF, Volume)', checked: settings.disableArrowKeys },
- { id: 'disableFKey', label: 'Disable F Key (Fullscreen)', checked: settings.disableFKey },
- { id: 'disableMKey', label: 'Disable M Key (Mute)', checked: settings.disableMKey },
- { id: 'disableSpeedControl', label: 'Disable Speed Control (Shift + > / <)', checked: settings.disableSpeedControl },
- { id: 'disableFrameSkip', label: 'Disable Frame Skip (`,` and `.`)', checked: settings.disableFrameSkip }
- ];
-
- checkboxes.forEach(hotkey => {
- let label = document.createElement('label');
- label.className = 'custom-checkbox';
-
- let checkbox = document.createElement('input');
- checkbox.type = 'checkbox';
- checkbox.id = hotkey.id;
- checkbox.checked = hotkey.checked;
-
- let checkmark = document.createElement('span');
- checkmark.className = 'checkmark';
-
- label.appendChild(checkbox);
- label.appendChild(checkmark);
- label.appendChild(document.createTextNode(` ${hotkey.label}`));
- content.appendChild(label);
- });
-
- modal.appendChild(content);
-
- // Create modal footer (save button)
- let footer = document.createElement('div');
- footer.className = 'modal-footer';
-
- let saveButton = document.createElement('button');
- saveButton.id = 'saveSettingsBtn';
- saveButton.className = 'primary-btn';
- saveButton.textContent = 'Save Settings';
- footer.appendChild(saveButton);
-
- modal.appendChild(footer);
-
- // Append modal to the document body
- document.body.appendChild(modal);
-
- // Create the overlay (dark background behind modal)
- let overlay = document.createElement('div');
- overlay.id = 'yt-hotkey-settings-overlay';
- overlay.className = 'modal-overlay';
- document.body.appendChild(overlay);
-
- // Close modal on clicking the close button or overlay
- closeButton.addEventListener('click', closeSettings);
- overlay.addEventListener('click', closeSettings);
-
- // Save settings on clicking the save button
- saveButton.addEventListener('click', function() {
- settings.disableNumericKeys = document.getElementById('disableNumericKeys').checked;
- settings.disableSpacebar = document.getElementById('disableSpacebar').checked;
- settings.disableArrowKeys = document.getElementById('disableArrowKeys').checked;
- settings.disableFKey = document.getElementById('disableFKey').checked;
- settings.disableMKey = document.getElementById('disableMKey').checked;
- settings.disableSpeedControl = document.getElementById('disableSpeedControl').checked;
- settings.disableFrameSkip = document.getElementById('disableFrameSkip').checked;
- GM_setValue('hotkeySettings', settings);
-
- // Show a success message and close modal after a short delay
- showNotification('Settings saved successfully!', modal);
- setTimeout(closeSettings, 1500);
- });
-
- // Function to close the settings modal
- function closeSettings() {
- modal.remove();
- overlay.remove();
- }
- }
-
- // Function to show a notification banner
- function showNotification(message, parentElement) {
- let banner = document.createElement('div');
- banner.className = 'notification-banner';
- banner.textContent = message;
- parentElement.appendChild(banner);
-
- setTimeout(() => banner.remove(), 3000);
- }
-
- // Register the settings menu command
- GM_registerMenuCommand('YouTube Hotkey Settings', openSettings);
-
- // Add styles for the modal and modern UI
- GM_addStyle(`
- /* General Modal Styling */
- .modal-card {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background-color: #fff;
- border-radius: 10px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- width: 400px;
- max-width: 90%;
- z-index: 10001;
- overflow: hidden;
- animation: slide-down 0.3s ease-out;
- }
-
- .modal-overlay {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.5);
- z-index: 10000;
- }
-
- .modal-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- background-color: #007bff;
- color: white;
- padding: 15px;
- }
-
- .modal-content {
- padding: 20px;
- }
-
- .modal-footer {
- display: flex;
- justify-content: flex-end;
- padding: 10px;
- border-top: 1px solid #ddd;
- }
-
- /* Checkbox Styling */
- .custom-checkbox {
- display: flex;
- align-items: center;
- margin-bottom: 10px;
- font-size: 16px;
- }
-
- .custom-checkbox input[type="checkbox"] {
- display: none;
- }
-
- .custom-checkbox .checkmark {
- display: inline-block;
- width: 18px;
- height: 18px;
- border: 2px solid #007bff;
- border-radius: 3px;
- margin-right: 10px;
- transition: all 0.2s;
- }
-
- .custom-checkbox input[type="checkbox"]:checked + .checkmark {
- background-color: #007bff;
- border-color: #007bff;
- }
-
- /* Button Styling */
- .primary-btn {
- background-color: #007bff;
- color: white;
- border: none;
- border-radius: 5px;
- padding: 10px 20px;
- cursor: pointer;
- transition: background-color 0.2s;
- }
-
- .primary-btn:hover {
- background-color: #0056b3;
- }
-
- /* Close Button */
- .close-btn {
- font-size: 24px;
- color: white;
- cursor: pointer;
- padding: 0 10px;
- }
-
- /* Notification Banner */
- .notification-banner {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- padding: 10px;
- background-color: #28a745;
- color: white;
- text-align: center;
- animation: fade-in-out 3s ease-out;
- }
-
- /* Animations */
- @keyframes slide-down {
- from { transform: translate(-50%, -60%); opacity: 0; }
- to { transform: translate(-50%, -50%); opacity: 1; }
- }
-
- @keyframes fade-in-out {
- 0%, 100% { opacity: 0; }
- 20%, 80% { opacity: 1; }
- }
- `);
- })();