// ==UserScript== // @name YouTube - Block Autoplay Preview (Keep Badge) // @name:vi YouTube - Chặn Preview Tự Động Khi Hover (Giữ Badge) // @namespace https://greasyfork.org/users/979364-miebie-1412 // @version 1.0 // @description Completely blocks YouTube thumbnail hover previews (animated WebP & video) while preserving progress badges, play buttons, and static images. Works on all pages: homepage, subscriptions, search, channels, etc. No permissions needed. Instant at page load. // @description:vi Chặn hoàn toàn hiệu ứng xem trước video khi di chuột qua thumbnail (WebP động & video), nhưng vẫn giữ nguyên badge tiến độ, nút play và ảnh tĩnh. Hoạt động trên mọi trang YouTube. // @author miebie.1412 // @match *://*.youtube.com/* // @match *://youtube.com/* // @grant none // @run-at document-start // @license MIT // @homepageURL https://greasyfork.org/en/users/979364-miebie-1412 // @supportURL https://greasyfork.org/en/users/979364-miebie-1412 // @icon https://www.youtube.com/favicon.ico // @compatible chrome // @compatible firefox // @compatible edge // @compatible opera // @compatible safari // @compatible brave // @downloadURL none // ==/UserScript== (function () { 'use strict'; // Polyfill for MutationObserver (enhanced for Safari/WebKit) if (typeof MutationObserver === 'undefined') { window.MutationObserver = window.WebKitMutationObserver || function(callback) { return { observe: function() {}, disconnect: function() {} }; }; } // Create and append CSS style safely const style = document.createElement('style'); style.textContent = ` ytd-moving-thumbnail-renderer, .ytd-moving-thumbnail-renderer, ytd-thumbnail-overlay-resume-playback-renderer, .ytd-thumbnail-overlay-resume-playback-renderer, .ytp-cued-thumbnail-overlay, .ytp-cued-thumbnail-overlay-image, ytd-thumbnail-overlay-loading-preview-renderer, .ytd-thumbnail-overlay-loading-preview-renderer, ytd-video-preview, .ytd-video-preview, #thumbnail-overlay-play, .thumbnail-overlay-play, #video-preview-container, .video-preview-container { display: none !important; visibility: hidden !important; } ytd-thumbnail img, .ytd-thumbnail img { transition: none !important; opacity: 1 !important; } #overlays, .ytd-rich-item-renderer #overlays, ytd-thumbnail[has-inline-playback-button] #overlays, ytd-thumbnail-overlay-toggle-pause-renderer, .ytd-thumbnail-overlay-pause-renderer { all: unset !important; display: block !important; } `; const appendStyle = () => { const target = document.head || document.documentElement; if (target && !target.querySelector('style[data-yt-block-preview]')) { style.setAttribute('data-yt-block-preview', 'true'); target.appendChild(style); } }; // Block preview elements with debounce to prevent performance issues let timeout; const blockPreview = () => { if (timeout) return; timeout = setTimeout(() => { document.querySelectorAll('img[src*="an_webp"], video[src*="an_webp"], img[src*="video-preview"], video[src*="video-preview"]').forEach(el => { if (el.tagName === 'IMG') { el.src = el.src.replace(/an_webp\/[^&]*&/g, '').replace(/video-preview\/[^&]*&/g, ''); el.srcset = ''; } else if (el.tagName === 'VIDEO') { el.src = el.src.replace(/an_webp\/[^&]*&/g, '').replace(/video-preview\/[^&]*&/g, ''); if (el.pause) el.pause(); if (el.currentTime !== undefined) el.currentTime = 0; el.removeAttribute('autoplay'); } }); timeout = null; }, 50); }; // Setup MutationObserver with fallback const observer = new MutationObserver(blockPreview); const observe = () => { if (document.documentElement) { observer.observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ['src', 'srcset'] }); } }; // Run on page load or when ready (Safari-safe) if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { appendStyle(); observe(); blockPreview(); }); } else { appendStyle(); observe(); blockPreview(); } // Periodic check every 500ms (lightweight) setInterval(blockPreview, 500); })();