您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Provide facilities to automatically enable RedGIFs audio in embedded iframes, and for communication regarding audio controls between the the hosting site and the iframe.
// ==UserScript== // @name RedGIFs iframe Sound Helper // @description Provide facilities to automatically enable RedGIFs audio in embedded iframes, and for communication regarding audio controls between the the hosting site and the iframe. // @license public domain // @version 1.4.1 // @grant none // @include https://www.redgifs.com/ifr/* // @namespace https://greasyfork.org/users/1258441 // ==/UserScript== const SOUND_DEFAULT = false; // false = off, true = on const LINK_DEFAULT = true; // false = link removed, true = link remains const urlParams = new URLSearchParams(window.location.search); function waitForElm(selector) { // Lovingly stolen from Yong Wang and sashaolm on StackOverflow return new Promise(resolve => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336 observer.observe(document.body, { childList: true, subtree: true }); }); } function toBoolean(argument) { if (argument === "true" || argument === "yes" || argument === "on" || argument === "1") { return true; } if (argument === "false" || argument === "no" || argument === "off" || argument === "0") { return false; } return undefined; // I could probably do this implicitly... } // Quick and dirty function to click an arbitrary element—not sure if elm.click() would work better? var click = function(elm) { var clickEvent = new MouseEvent("click", { "bubbles": true, "cancelable": false, "view": window }); elm.dispatchEvent(clickEvent); }; // Facilities for enabling or disabling click-to-open link on the video var saved_link = null; function disableHyperLink(hyperlink) { if (hyperlink.tagName !== "A") { return; } if (saved_link === null) { saved_link = hyperlink.href; } hyperlink.href = "javascript: void(0)"; hyperlink.target = "_self"; } function enableHyperLink(hyperlink) { if (hyperlink.tagName !== "A" || saved_link === null) { return; } hyperlink.href = saved_link; hyperlink.target = "_blank"; } // Facilities for turning looping on and off var video_end_listener = (event) => window.parent.postMessage("gfy_ended", "*") function disableLoop(video) { if (video.tagName !== "VIDEO") { return; } video.removeAttribute("loop"); video.addEventListener("ended", function(event) {window.dispatchEvent(event);}); video.addEventListener("ended", video_end_listener); } function enableLoop(video) { if (video.tagName !== "VIDEO") { return; } video.setAttribute("loop", ""); video.removeEventListener("ended", video_end_listener); } // Setup configuration const query_sound = toBoolean(urlParams.get("sound")); const query_link = toBoolean(urlParams.get("link")); const query_loop = toBoolean(urlParams.get("loop")); const hash = window.location.hash; var autoenable_sound = undefined; var autodisable_link = undefined; var autodisable_loop = undefined; // Figure out whether to enable sound if (query_sound === true) { autoenable_sound = true; } else if (query_sound === false) { // do nothing if it's undefined autoenable_sound = false; } if (window.location.hash === "#sound") { autoenable_sound = true; } else if (window.location.hash === "#nosound") { autoenable_sound = false; } if (autoenable_sound === undefined) { autoenable_sound = SOUND_DEFAULT; } // Figure out whether to disable the link if (query_link === true) { autodisable_link = false; } else if (query_link === false) { autodisable_link = true; } if (autodisable_link === undefined) { autodisable_link = !LINK_DEFAULT; } // Figure out whether to disable looping autodisable_loop = !query_loop; // loop should be ON by default // Execute the above settings if (autoenable_sound) { waitForElm(".soundOff").then(click); } if (autodisable_link) { waitForElm(".videoLink").then(disableHyperLink) } if (autodisable_loop) { waitForElm("video").then(disableLoop); } window.parent.postMessage("gfy_enhanced_api", "*"); // For communication with the parent window window.onmessage = function(message) { const soundButton = document.querySelector(".soundOff") || document.querySelector(".soundOn"); const loaded = soundButton !== null; switch (message.data) { case "soundOn": /* If the page is not loaded yet and sound will be off when it loads, wait for it to load then click .soundOff * If the page is not loaded yet and sound will be on when it loads, do nothing * If the page is loaded, look for .soundOff and click if present * * I worked it out, this is the only way to make it work. */ if (loaded) { let button = document.querySelector(".soundOff"); if (button !== null) click(button); } else if (!autoenable_sound) waitForElm(".soundOff").then(click); break; case "soundOff": /* If the page is not loaded yet and sound will be off when it loads, do nothing * If the page is not loaded yet and sound will be on when it loads, wait for it to load then click .soundOn * If the page is loaded, look for .soundOn and click if present */ if (loaded) { let button = document.querySelector(".soundOn"); if (button !== null) click(button); } else if (autoenable_sound) waitForElm(".soundOff").then(click); break; case "soundToggle": click(soundButton); break; case "linkOff": waitForElm(".videoLink").then(disableHyperLink); break; case "linkOn": waitForElm(".videoLink").then(enableHyperLink); break; case "loopOff": waitForElm("video").then(disableLoop); break; case "loopOn": waitForElm("video").then(enableLoop); break; case "pause": waitForElm("video").then((vid) => vid.pause()); break; case "play": waitForElm("video").then((vid) => vid.play()); break; default: console.error("Unknown command " + message.data); } }