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.

اعتبارا من 07-02-2024. شاهد أحدث إصدار.

// ==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"));
  }
}