RedGIFs iframe Sound Helper

Provide facilities to automatically enable RedGIFs audio in embedded iframes, and for communication regarding audio controls between the the hosting site and the iframe.

当前为 2024-02-07 提交的版本,查看 最新版本

// ==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.1
// @grant    none
// @include  https://www.redgifs.com/ifr/*
// @namespace https://greasyfork.org/users/1258441
// ==/UserScript==

const SOUND_DEFAULT = false;

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
    });
  });
}

var click = function(elm) {
  var clickEvent = new MouseEvent("click", {
    "bubbles": true,
    "cancelable": false,
    "view": window
  });
  elm.dispatchEvent(clickEvent);
};

const query_sound = urlParams.get("sound");
const hash = window.location.hash;

var sound_on = undefined;

if (query_sound === "true" || query_sound === "yes" || query_sound === "on" || query_sound === "1") {
  sound_on = true;
} else if (query_sound === "false" || query_sound === "no" || query_sound === "off" || query_sound === "0") {
  sound_on = false;
}

if (window.location.hash === "#sound") {
  sound_on = true;
} else if (window.location.hash === "#nosound") {
  sound_on = false;
}

if (sound_on === null) {
  sound_on = SOUND_DEFAULT;
}

if (sound_on) {
  waitForElm(".soundOff").then(click);
}
else {
  //default behavior
}

// For communication with the parent window
window.onmessage = function(message) {
  if (message.data === "soundOn") {
    /* If the page is not loaded yet, wait for it to load then click .soundOff.
     * If it is loaded, and sound is off, click .soundOff immediately
     * If it is loaded, and sound is on, do nothing.
     *
     * It has to do nothing instead of adding a waitForElm because if we did that, then when this is called
     * while sound is on, it'll wait for sound to be manually turned off then turn it back on.
     */
    if (document.querySelector(".soundOn") === null) {
      waitForElm(".soundOff").then(click);
    }
  }
  else if (message.data === "soundOff") {
    /* If the page is not loaded yet, do nothing.
     * If it is loaded, and sound is off, do nothing.
     * If it is loaded, and sound is on, click .soundOn immediately.
     */
    let soundOnElement = document.querySelector(".soundOn");
    if (soundOnElement !== null) {
      click(soundOnElement);
    }
  }
  else if (message.data === "soundToggle") {
    // If the sound is on, turn it off. If the sound is off, turn it on.
    click(document.querySelector(".soundOff") || document.querySelector(".soundOn"));
  }
}