5 ms·
User side solution click 2 load for ublock users(note that chrome is transitioning to manifest v3 and might not work) is the following thanks to yokoffing/filte
by user070223 2y ago
User side solution click 2 load for ublock users(note that chrome is transitioning to manifest v3 and might not work) is the following thanks to yokoffing/filterlists
https://raw.githubusercontent.com/yokoffing/filterlists/main/click2load.txt https://raw.githubusercontent.com/yokoffing/filterlists/main...
(Betterfox creator, he has other useful filters on github)
!||youtube-nocookie.com^$3p,frame,redirect=click2load.html,domain=~bing.com|~google.com|~duckduckgo.com|~video.search.yahoo.com
||youtube-nocookie.com/embed^$3p,frame,redirect=click2load.html,domain=~bing.com|~google.com|~duckduckgo.com|~video.search.yahoo.com
||youtube.com^$3p,frame,redirect=click2load.html,domain=~bing.com|~chatreplay.stream|~google.com|~duckduckgo.com|~video.search.yahoo.com
- schiffern 2y agoClick2load is an improvement, but embeds still suck. All I want is a plain link, so a while back I got fed up and wrote a short userscript to just rewrite the page. Works surprisingly well for how simple it is. // ==UserScript== // @name Youtube UnEmbed // @version 0.1 // @description Converts embedded Youtube iframes into links // @match *://*/* // @exclude *://*.youtube.com/* // @exclude *://*.reddit.com/* // @exclude *://looptube.io/* // @grant none // @run-at document-idle // ==/UserScript== (function() { 'use strict'; const SITE = "https://www.youtube.com"; //m.youtube Invidious etc const LINK_TO_TIMESTAMP = true; const SHOW_PREVIEW_IMAGE = false; const replaceEmbeds = () => { document.querySelectorAll('iframe').forEach((frame) => { const frameURL = frame.src || frame.dataset?.src; if (!frameURL) return; const match = frameURL.match(/(^https?:)?\/\/(www\.)?youtube(-nocookie)?\.com\/embed\/([a-zA-Z0-9\-_]{11}).*?(\?.*((t|start)=([\dsmh]*)))?/i); if (match?.length == 9) { const newURL = SITE+"/watch?" + ((LINK_TO_TIMESTAMP && match[8]) ? "t="+match[8]+"&" : "") + "v="+match[4]; const elem = document.createElement("a") elem.href = newURL; if (SHOW_PREVIEW_IMAGE) { let img = document.createElement("img"); img.src = "https://i.ytimg.com/vi/"+match[4]+"/mqdefault.jpg"; img.alt="Preview image of Youtube video"; // 320 x 180 preview. For more resolution options see // https://medium.com/@viniciu_/how-to-get-the-default-thumbnail-url-for-a-youtube-video-b5497b3b6218 elem.appendChild(img); } else { elem.innerHTML = newURL; } frame.outerHTML = elem.outerHTML; // common lazyload hiding methods elem.style.display = "block !important"; elem.style.opacity = "100% !important"; elem.style.background = "transparent !important"; const parent = elem.parentElement; if (parent) { parent.style.display = "block !important"; parent.style.opacity = "100% !important"; parent.style.background = "transparent !important"; } } }); }; replaceEmbeds(); setInterval(replaceEmbeds, 3000); })();
- KomoD 2y agoI suggest using MutationObserver instead of just running the replaceEmbeds function every 3s.
- schiffern 2y agoIntentionally left as an exercise for the reader. ;-D If you do, share it back! I'll switch to your version. Remember I threw this together in about half an hour, and maybe that amount of cleanup to post here. "Works for me" is the order of the day. The extra debugging alone would be longer than the whole project! Besides, the function that runs is so light it doesn't really seem worth it. It could even make performance worse, since for reliability you need to observe mutations across the entire DOM, which could occur a lot more often. So for performance you want to add some debouncing too, adding yet more complexity to what's supposed to be a 'quick and dirty' fix.
- eikaramba 2y agohere it is. i am however showing the preview image and replacing it with the iframe on click. basically click2load. by using mutationobserver it seems i don't need ublock to block the iframe, because as soon as the browser tries to include it on the page it gets replaced anyway (function() { 'use strict'; const SITE = "https://www.youtube.com"; const LINK_TO_TIMESTAMP = true; const SHOW_PREVIEW_IMAGE = true; const createPreviewElement = (videoId, newURL, frame) => { const container = document.createElement("div"); container.setAttribute('data-yt-preview', 'true'); container.style.position = "relative"; container.style.width = frame.width + "px"; container.style.height = frame.height + "px"; container.style.cursor = "pointer"; const img = document.createElement("img"); img.src = `https://i.ytimg.com/vi/${videoId}/mqdefault.jpg`; img.alt = "Preview image of Youtube video"; img.style.width = "100%"; img.style.height = "100%"; img.style.objectFit = "cover"; const playButton = document.createElement("div"); playButton.innerHTML = "▶"; playButton.style.position = "absolute"; playButton.style.top = "50%"; playButton.style.left = "50%"; playButton.style.transform = "translate(-50%, -50%)"; playButton.style.fontSize = "48px"; playButton.style.color = "white"; playButton.style.backgroundColor = "rgba(0, 0, 0, 0.7)"; playButton.style.borderRadius = "50%"; playButton.style.width = "80px"; playButton.style.height = "80px"; playButton.style.display = "flex"; playButton.style.justifyContent = "center"; playButton.style.alignItems = "center"; container.appendChild(img); container.appendChild(playButton); container.addEventListener("click", () => { const iframe = document.createElement("iframe"); iframe.src = frame.src + (frame.src.includes('?') ? '&' : '?') + 'autoplay=1'; iframe.width = frame.width; iframe.height = frame.height; iframe.frameBorder = "0"; iframe.allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"; iframe.allowFullscreen = true; iframe.setAttribute('data-yt-processed', 'true'); container.parentNode.replaceChild(iframe, container); }); return container; }; const replaceEmbed = (frame) => { const frameURL = frame.src || frame.dataset?.src; if (!frameURL) return; const match = frameURL.match(/(^https?:)?\/\/(www\.)?youtube(-nocookie)?\.com\/embed\/([a-zA-Z0-9\-_]{11}).*?(\?.*((t|start)=([\dsmh]*)))?/i); if (match?.length == 9) { const videoId = match[4]; const newURL = SITE + "/watch?" + ((LINK_TO_TIMESTAMP && match[8]) ? "t=" + match[8] + "&" : "") + "v=" + videoId; const previewElement = createPreviewElement(videoId, newURL, frame); frame.parentNode.replaceChild(previewElement, frame); // common lazyload hiding methods previewElement.style.display = "block !important"; previewElement.style.opacity = "100% !important"; previewElement.style.background = "transparent !important"; const parent = previewElement.parentElement; if (parent) { parent.style.display = "block !important"; parent.style.opacity = "100% !important"; parent.style.background = "transparent !important"; } } }; const observeDOM = () => { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'childList') { mutation.addedNodes.forEach((node) => { if (node.nodeType === Node.ELEMENT_NODE) { if (node.tagName === 'IFRAME' && !node.hasAttribute('data-yt-processed')) { replaceEmbed(node); } else { node.querySelectorAll('iframe:not([data-yt-processed])').forEach(replaceEmbed); } } }); } }); }); observer.observe(document.body, { childList: true, subtree: true }); }; // Initial replacement document.querySelectorAll('iframe:not([data-yt-processed])').forEach(replaceEmbed); // Start observing DOM changes observeDOM(); })();