Sleazy Fork is available in English.
Hide the controls overlay on Onlyfans video player
// ==UserScript==
// @name OnlyFans - Hide Video Controls Overlay
// @version 0.6.3
// @description Hide the controls overlay on Onlyfans video player
// @author pipstar
// @match https://onlyfans.com/*
// @run-at document-start
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiI+PHJlY3QgeD0iMiIgeT0iMTAuNSIgd2lkdGg9IjI4IiBoZWlnaHQ9IjExIiByeD0iMy4yIiBmaWxsPSIjMDBBRkYwIi8+PHBhdGggZD0iTTcgMTMuNCBMNyAxOC42IEwxMS40IDE2IFoiIGZpbGw9IiNmZmYiLz48cmVjdCB4PSIxMy41IiB5PSIxNS4xIiB3aWR0aD0iMTQiIGhlaWdodD0iMS44IiByeD0iMC45IiBmaWxsPSIjZmZmIiBvcGFjaXR5PSIwLjQ1Ii8+PHJlY3QgeD0iMTMuNSIgeT0iMTUuMSIgd2lkdGg9IjYiIGhlaWdodD0iMS44IiByeD0iMC45IiBmaWxsPSIjZmZmIi8+PGNpcmNsZSBjeD0iMTkuNSIgY3k9IjE2IiByPSIyLjQiIGZpbGw9IiNmZmYiLz48bGluZSB4MT0iNCIgeTE9IjI4IiB4Mj0iMjgiIHkyPSI0IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iNiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PGxpbmUgeDE9IjQiIHkxPSIyOCIgeDI9IjI4IiB5Mj0iNCIgc3Ryb2tlPSIjZmYyZDU1IiBzdHJva2Utd2lkdGg9IjMuNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9zdmc+
// @license MIT
// @namespace https://greasyfork.org/users/1275465
// ==/UserScript==
(function () {
'use strict';
/* ------------------------------------------------------------------ *
* CONFIG - which elements count as "the controls" the toggle governs.
* ------------------------------------------------------------------ */
const HIDE_CONTROL_BAR = true; // bottom bar: play, scrubber, volume, quality, fullscreen, "record"
const HIDE_BIG_PLAY_BUTTON = true; // large centered play button overlay
const selectors = [];
if (HIDE_CONTROL_BAR) selectors.push('.video-js .vjs-control-bar');
if (HIDE_BIG_PLAY_BUTTON) selectors.push('.video-js .vjs-big-play-button');
const HIDE_CSS = `${selectors.join(',\n')} {
display: none !important;
opacity: 0 !important;
pointer-events: none !important;
}`;
/* ------------------------------------------------------------------ *
* STATE - persisted across page loads. Defaults to hidden.
* ------------------------------------------------------------------ */
const STORAGE_KEY = 'of_controls_hidden';
let hidden = GM_getValue(STORAGE_KEY, true);
// Single <style> element we flip on/off. Injected at document-start so
// the bar never flashes when controls are meant to be hidden.
const style = document.createElement('style');
style.id = 'of-hide-controls-style';
(document.head || document.documentElement).appendChild(style);
function applyState() {
// When hidden, inject the rules; when shown, clear them so video.js
// resumes its normal hover/autohide behavior. Updates live.
style.textContent = (hidden && selectors.length) ? HIDE_CSS : '';
}
/* ------------------------------------------------------------------ *
* MENU TOGGLE - appears in the Tampermonkey popup under this script.
* Re-registered on each toggle so its label reflects the current state.
* ------------------------------------------------------------------ */
let menuId;
function registerMenu() {
if (menuId !== undefined && typeof GM_unregisterMenuCommand === 'function') {
try { GM_unregisterMenuCommand(menuId); } catch (e) { /* older TM */ }
}
const label = hidden
? 'Video controls: HIDDEN \u2014 click to show (Ctrl+Alt+V)'
: 'Video controls: SHOWN \u2014 click to hide (Ctrl+Alt+V)';
menuId = GM_registerMenuCommand(label, toggle);
}
function toggle() {
hidden = !hidden;
GM_setValue(STORAGE_KEY, hidden);
applyState();
registerMenu(); // refresh the menu label
}
/* ------------------------------------------------------------------ *
* FULLSCREEN HELPERS - target the .video-js container, not the raw
* <video>, so the browser doesn't draw its own native controls.
* ------------------------------------------------------------------ */
function pickPlayer() {
const players = [...document.querySelectorAll('.video-js')];
if (!players.length) return null;
// Prefer a player that's actually playing.
const playing = players.find(p => {
const v = p.querySelector('video');
return v && !v.paused && !v.ended && v.readyState > 2;
});
if (playing) return playing;
// Otherwise, the one with the largest visible area in the viewport.
let best = null, bestArea = -1;
for (const p of players) {
const r = p.getBoundingClientRect();
const w = Math.max(0, Math.min(r.right, innerWidth) - Math.max(r.left, 0));
const h = Math.max(0, Math.min(r.bottom, innerHeight) - Math.max(r.top, 0));
const area = w * h;
if (area > bestArea) { bestArea = area; best = p; }
}
return best || players[0];
}
function toggleFullscreen() {
const fsEl = document.fullscreenElement || document.webkitFullscreenElement;
if (fsEl) {
(document.exitFullscreen || document.webkitExitFullscreen || function () {}).call(document);
return;
}
const el = pickPlayer();
if (!el) return;
const req = el.requestFullscreen || el.webkitRequestFullscreen;
if (req) req.call(el);
}
/* ------------------------------------------------------------------ *
* KEYBOARD SHORTCUTS
* Ctrl+Alt+V : toggle controls (works regardless of state)
* F : fullscreen the video, ONLY while controls are hidden
* and only when not typing in a field. Press again (or
* Esc) to exit.
* Uses e.code (physical key) so it's layout-independent.
* ------------------------------------------------------------------ */
function isTyping(e) {
const t = e.target;
if (!t) return false;
return t.isContentEditable ||
t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.tagName === 'SELECT';
}
document.addEventListener('keydown', e => {
// Ctrl+Alt+V -> toggle controls
if (e.ctrlKey && e.altKey && !e.shiftKey && !e.metaKey &&
(e.code === 'KeyV' || (e.key && e.key.toLowerCase() === 'v'))) {
e.preventDefault();
e.stopPropagation();
toggle();
return;
}
// F (no modifiers) -> fullscreen, only while controls are hidden
if (!e.ctrlKey && !e.altKey && !e.metaKey && !e.shiftKey &&
(e.code === 'KeyF' || (e.key && e.key.toLowerCase() === 'f'))) {
if (hidden && !isTyping(e)) {
e.preventDefault();
e.stopPropagation();
toggleFullscreen();
}
}
}, true); // capture phase so we act before the page's own handlers
/* ------------------------------------------------------------------ *
* BOOT
* ------------------------------------------------------------------ */
applyState();
registerMenu();
})();