BetterTeddit

Extensible convenience extension for Teddit instances while keeping general JavaScript disabled.

当前为 2022-10-07 提交的版本,查看 最新版本

// ==UserScript==
// @name        BetterTeddit
// @namespace   betterteddit
// @match       https://*.teddit.net/*
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_addValueChangeListener
// @grant       GM_addStyle
// @run-at      document-start
// @version     1.1.0
// @author      Hououin Kyōma
// @license     GPLv3
// @description Extensible convenience extension for Teddit instances while keeping general JavaScript disabled.
// ==/UserScript==

/* === README.md ===
# Read Me

Lightweight extensible userscript for Teddit instances for Reddit.

Right now recommend keep Teddit preferences empty, and dark theme. Changes to Teddit may break the script, please let me know if it does.

Access to javascript you can audit in advance. Turn auto-update off, audit before update.

On a Teddit instance if there were any javascript you would have no guarantee the host didn't modify any included javascript at random one day.

You have no guarantees about their backend in regards to tracking, but at least you won't be part of someone's mining botnet.

Not even Forced Anonymous and Hide Points can save this irredeemably useless platform from being destroyed by its own design,
but at least this script will make it ever so slightly more bearable when you are forced to read a Reddit thread for whatever reason.

# Features

Most features can easily be toggled on or off.

- Expand Images toggle.
- Auto expand all.
- Image click and drag resize.
- Fixed navbar with navigation links.
- Forced Anonymous
- Hide Points
- Less branding

[Demo extension with included features for User IDs and colorized IDs](https://gf.qytechs.cn/en/scripts/452561-betterteddit-extension-user-ids).

*/

/* === CHANGELOG.md ===
# Changelog

### v1.1.0 2022-10-07
- Two Image Resizing bugs have been dealt with.
This changes the image containers when browsing sub feeds.

### v1.0 Alpha Release
*/


/* === KNOWNBUGS.md ===
# Known Bugs
- DOMContentLoaded very rarely does not fire.
*/

var events = [];
var header, header_left, header_right;
var expanded = false;
var images_button;
var pref_button;
var pref_container = false;

// These are just defaults, change the GM values or use the new preferences button in the header.
const config = {
    expand_images: {
      name: "Expand Images Button",
      desc: "Button to toggle expand all images.",
      default: true
    },
    auto_expand_images: {
      name: "Auto Expand Images",
      desc: "Expands all images automatically.",
      default: false
    },
    image_resizer: {
      name: "Image Resizer",
      desc: "Click and drag to resize images.",
      default: true
    },
    forced_anonymous: {
      name: "Forced Anonymous",
      desc: "Replace names with Anonymous.",
      default: true
    },
    hide_points: {
      name: "Hide Points",
      desc: "Hides all voting points.",
      default: true
    },
    hide_user_flair: {
      name: "Hide User Flairs",
      desc: "Hides all user flairs.",
      default: true
    },
    hide_submission_flair: {
      name: "Hide Submission Flairs",
      desc: "Hides all submission flairs.",
      default: true
    },
    unbranding: {
      name: "Unbranding",
      desc: "Remove superflous site branding.",
      default: true
    },
    navigator: {
      name: "Navigation Links",
      desc: "Adds [Prev] and [Next] links to header.",
      default: true
    },
    event_mode: {
      name: "Event Mode",
      desc: "Dispatches events for BetterTeddit extensions.",
      default: true
    },
    debug_mode: {
      name: "Debug Mode",
      desc: "Enables console.log(), useful for developers and debugging.",
      default: true
    }
}

function insert_before(new_node, existing_node) {
  existing_node.parentNode.insertBefore(new_node, existing_node);
}

function log(message) {
  if (GM_getValue("debug_mode") == true) {
    if (typeof message == "string") {
      console.log("BetterTeddit: " + message);
    } else {
      console.log(message);
    }
  }
}

function dispatch_event(event_name) {
  if (GM_getValue("event_mode") != true) {
    return false;
  }
  if (events[""+event_name+""] == undefined) {
    events.push(""+event_name+"");
    events[""+event_name+""] = new CustomEvent(""+event_name+"", {
      detail: {
        event_name: ""+event_name+""
      }
    });
    window.addEventListener(""+event_name+"", (event) => {
      log("Dispatched Event: "+event_name+".");
    });
  }
  window.dispatchEvent(events[""+event_name+""]);
}

log("Start of Script");
dispatch_event("before_startup");

function init_values() {
  dispatch_event("before_init_values");
  function check_value(key, value) {
    if (GM_getValue(key) == undefined) {
      GM_setValue(key, value);
      log("Undefined, Setting default: [" + key + "]");
      log(value);
    } else {
      log("Value found, Getting value: [" + key + "]");
      log(GM_getValue(key));
    }
  }
  Object.entries(config).forEach( (key, value) => {
    check_value(key[0], key[1]["default"]);
  });
  dispatch_event("after_init_values");
} init_values();

function add_style() {
  dispatch_event("before_add_style");

  style = `
    html {
     --header-size: 10pt;
     --header-color: rgb(117, 117, 117);
     --header-background: #252525;
     --header-border-bottom: 1px solid #000;
     --header-box-shadow: 0 0 2px 0 #000;
     --header-a-color: rgb(199, 199, 199);
     --header-a-color-hover: #fff;
    }

    body {
      margin: var(--header-size) 0 0 0;
      padding: 0;
      background: #0F0F0F;
      font-family: sans-serif;
    }

    a.noclick {
      text-decoration: none !important;
      color: inherit !important;
      font-size: inherit!important;
    }

    div#bt_header {
      line-height: 1.1;
      font-size: var(--header-size);
      color: var(--header-color);
      display: flex;
      justify-content: space-between;
      width: 100%;
      position: fixed;
      top: 0;
      background: var(--header-background);
      z-index: 1000;
      padding: 2px 4px;
      border-bottom: var(--header-border-bottom);
      box-shadow: var(--header-box-shadow);
    }
    div#bt_header a, div#bt_header a:visited, div#pref_preferences a, div#pref_preferences a:visited {
      cursor: pointer;
      color: var(--header-a-color);
      text-decoration: none;
    }
    div#bt_header a:hover, div#pref_preferences a:hover {
      color: var(--header-a-color-hover);
    }
    div#bt_header > span {
      display: flex;
    }
    span.header_bracket {
      display: inline-flex;
      margin: 0 2px;
      -webkit-user-select:none;
      user-select: none;
    }
    span#bt_header_right {
      padding-right: 1em;
    }

    #pref_container {
      z-index: 100;
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
    }
    #pref_backdrop {
      z-index: 100;
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      background: rgba(0, 0, 0, 0.5);
    }
    #pref_preferences {
      z-index: 1000;
      position: fixed;
      top: calc( var(--header-size) + 10px);
      left: 0;
      right: 0;
      max-width: 500px;
      min-width: 500px;
      min-height: 500px;
      margin: auto;
      background: var(--header-background);
      border: var(--header-border-bottom);
      box-shadow: var(--header-box-shadow);
    }
    #pref_nav_container {
      display: flex;
      margin: 10px;
      border-bottom: 1px solid #000;
      padding-bottom: 2px;
      font-size: 10pt;
    }
    #pref_nav, #pref_nav_right {
      display:flex;
    }
    #pref_nav > span, #pref_nav_right > span {
      margin: 0 4px;
    }
    #pref_nav span[selected], #pref_nav_right span[selected] {
      font-weight:bold;
    }
    #pref_nav_right {
      margin: 0 1em 0 auto;
    }
    #pref_close {
      font-size: 1.5em;
      font-weight: bold;
      line-height: 0.5;
    }
    #pref_content {
      margin: 1em;
      max-height: 500px;
      padding-bottom: 1em;
      overflow-y: scroll;
    }
    #pref_content fieldset {
      border: 1px solid #000;
      font-size: 0.8em;
      margin-bottom: 0.5em;
    }
    #pref_content a {
      text-decoration: underline!important;
    }
    #pref_content fieldset legend {
      margin-left: 0.5em;
      font-weight: bold;s
    }
    #pref_content ul {
      list-style: none;
      margin-left: 1em;
    }
    #pref_content li input, #pref_content li label, #pref_content li span {
      margin: 0 0.1em;
    }
    #pref_preferences label {
      -webkit-user-select: none;
              user-select: none;
    }
    #pref_preferences label::after {
      content: ':'
    }

  `;
  GM_addStyle(style);

  dispatch_event("after_add_style");
}

function create_header() {
  dispatch_event("before_create_header");
  header = document.createElement("div");
  header.id = "bt_header";

  header_left = document.createElement("span");
  header_left.id = "bt_header_left";
  header.appendChild(header_left);
  header_right = document.createElement("span");
  header_right.id = "bt_header_right";
  header.appendChild(header_right);

  header_left.innerHTML = `
    <span class="header_bracket" id="header_home">[<a href="/">Home</a>]</span>
    <span class="header_bracket" id="header_top">[<a href="#top">Top</a>]</span>
    <span class="header_bracket" id="header_bottom">[<a href="#bottom">Bottom</a>]</span>
  `;

  dispatch_event("during_create_header"); // After fully defined, but before placed on page.
  document.body.prepend(header);
  dispatch_event("after_create_header");

}

function user_tag() {
  dispatch_event("before_user_tag");
  var users = document.querySelectorAll("div.link p.submitted a,div.title p.submitted a,div.comment p.author a:not([title='submitter'])");
  [...users].forEach( (user) => {
    if (user.textContent == "[deleted]") {
      return false;
    }
    user.setAttribute("user", user.getAttribute("href"));
  });
  dispatch_event("after_user_tag");
}

function move_links() {
  dispatch_event("before_move_links");
  var threads = document.querySelectorAll("div.entry");
  [...threads].forEach( (thread) => {
    var links_container = document.createElement("div");
    links_container.classList.add("links_container");
    var links = thread.querySelectorAll("div.links > a, div.links > span.tag");
    [...links].forEach( (link) => {
      links_container.appendChild(link);
    });
    thread.querySelector("div.links").prepend(links_container);
  });
  dispatch_event("after_move_links");
}

function move_details() {
  dispatch_event("before_move_details");
  var threads = document.querySelectorAll("div.entry");
  [...threads].forEach( (thread) => {
    var details_container = document.createElement("div");
    details_container.classList.add("details_container");
    var details = thread.querySelectorAll("div.links > details, div.links > style");
    [...details].forEach( (detail) => {
      details_container.appendChild(detail);
    });
    thread.querySelector("div.links").appendChild(details_container);
  });
  dispatch_event("after_move_details");
}

function forced_anonymous() {
  if (GM_getValue("forced_anonymous") != true) {
    return false;
  }
  dispatch_event("before_forced_anonyous");
  var users = document.querySelectorAll("a[user]");
  [...users].forEach( (user) => {
    if (user.textContent == "[deleted]") {
      return false;
    }
    user.removeAttribute("href");
    user.textContent = "Anonymous";
    user.classList.add("noclick");
  });
  dispatch_event("after_forced_anonymous");
}

function hide_points() {
  if (GM_getValue("hide_points") != true) {
    return false;
  }
  dispatch_event("before_hide_points");
  var style = document.createElement("style");
  style.innerHTML = ".score, .upvotes {visibility: hidden}.ups {display: none!important;}";
  style.id = "bt_hide_points";
  document.head.appendChild(style);
  GM_addValueChangeListener("hide_points", function() {
    if (arguments[2] == true) {
      style.innerHTML = ".score, .upvotes {visibility: hidden}.ups {display: none!important;}";
    } else {
      style.innerHTML = "/* hide_points disabled */";
    }
  });
  dispatch_event("after_hide_points");
}

function hide_user_flair() {
  if (GM_getValue("hide_user_flair") != true) {
    return false;
  }
  dispatch_event("before_hide_user_flair");
  var style = document.createElement("style");
  style.innerHTML = "p.submitted .flair, .meta p .flair { display: none!important; }";
  style.id = "bt_hide_user_flair";
  document.head.appendChild(style);
  GM_addValueChangeListener("hide_user_flair", function() {
    if (arguments[2] == true) {
      style.innerHTML = "p.submitted .flair, .meta p .flair { display: none!important; }";
    } else {
      style.innerHTML = "/* hide_user_flair disabled */";
    }
  });
  dispatch_event("after_hide_user_flair");
}

function hide_submission_flair() {
  if (GM_getValue("hide_submission_flair") != true) {
    return false;
  }
  dispatch_event("before_hide_submission_flair");
  var style = document.createElement("style");
  style.innerHTML = ".title .flair { display: none!important; }";
  style.id = "bt_hide_submission_flair";
  document.head.appendChild(style);
  GM_addValueChangeListener("hide_submission_flair", function() {
    if (arguments[2] == true) {
      style.innerHTML = ".title .flair { display: none!important; }";
    } else {
      style.innerHTML = "/* hide_submission_flair disabled */";
    }
  });
  dispatch_event("after_hide_submission_flair");
}

function unbranding() {
  if (GM_getValue("unbranding") != true) {
    return false;
  }
  dispatch_event("before_unbranding");

  var teddit_text = document.querySelector("header a.main");
  if (teddit_text != null) { teddit_text.remove(); }

  var subreddit_text = document.querySelector("header div p");
  if (subreddit_text != null) { subreddit_text.remove(); }

  var sub_link = document.querySelector("header div a p");
  if (sub_link != null) { sub_link.textContent = sub_link.textContent.substring(3); }

  var sub_title = document.querySelector("div#sidebar div.content div.heading p.title");
  if (sub_title != null) { document.title = sub_title.textContent; }

  var teddit_intro = document.getElementById("intro");
  if (teddit_intro != null) { teddit_intro.remove(); }

  GM_addValueChangeListener("unbranding", function() {
    if (arguments[2] == true) {

    } else {

    }
  });
  dispatch_event("after_unbranding");
}

function expand_images() {
  dispatch_event("before_expand_images")

  //var images = document.querySelectorAll("div.links details.preview-container"); //images only
  var images = document.querySelectorAll("div.links details"); //text too
  log("Found "+images.length+" images.");
  [...images].forEach( (image) => {
    if (expanded != true) {
      image.setAttribute("open", "open");
    } else {
      image.setAttribute("open", "");
      image.removeAttribute("open");
    }
  });
  expanded = expanded?false:true;

  dispatch_event("after_expand_images");
}

function expand_images_button() {
  if (GM_getValue("expand_images") != true) {
    return false;
  }
  dispatch_event("before_expand_images_button");

  images_button = document.createElement("span");
  images_button.id = "header_images_button";
  images_button.classList.add("header_bracket");
  images_button.innerHTML = `
    [<a>Expand</a>]
  `;
  images_button.addEventListener("click", expand_images);

  header_left.appendChild(images_button);

  GM_addValueChangeListener("expand_images", function() {
    if (arguments[2] == true) {
      images_button.style.display = "unset";
    } else {
      images_button.style.display = "none";
    }
  });

  dispatch_event("after_expand_images_button");
}

function auto_expand_images() {
  if (GM_getValue("auto_expand_images") != true) {
    return false;
  }
  dispatch_event("before_auto_expand_images");
  expand_images(true);
  dispatch_event("after_auto_expand_images");
}

function image_resizer() {
  if (GM_getValue("image_resizer") != true) {
    return false;
  }
  dispatch_event("before_image_resizer");

  function resize(image, event) {
    log("Image Resize: Mouse Down");
    event.preventDefault();
    var mousedown = true;
    var imageX, imageY, posX, posY, newposX, newposY, diffX, diffY, newimageX, newimageY;

    image.style.minWidth = "25px";
    image.style.minHeight = "25px";
    imageX = image.offsetWidth;
    imageY = image.offsetHeight;
    posX = event.clientX;
    posY = event.clientY;
    //log(imageX); log(imageY);
    //log(posX);   log(posY);
    image.style.width = imageX + "px";
    image.style.height = imageY + "px";
    image.style.maxWidth = "unset";
    image.style.maxHeight = "unset";

    function mousemove(e) {
      if (mousedown == false) {
        log("Image Resize: Mouse Down is false.");
      }
      log("Image Resize: Mouse Move");
      newposX = e.clientX;
      newposY = e.clientY;
      diffX = newposX - posX;
      diffY = newposY - posY;
      newimageX = imageX + diffX + diffY;
      newimageY = imageY + diffX + diffY;
      image.style.width = newimageX + "px";
      image.style.height = "auto";
    }
    window.addEventListener("mousemove", mousemove);

    function mouseup() {
      mousedown = false;
      log("Image Resize: Mouse Up");
      window.removeEventListener("mouseup", mouseup);
      window.removeEventListener("mousemove", mousemove);
    }
    window.addEventListener("mouseup", mouseup );

  }
  // Sub images
  var sub_images = document.querySelectorAll("details.preview-container");
  [...sub_images].forEach( (details) => {
    details.querySelector("div.preview").remove();
    details.style.zIndex = 2;
    details.style.position = "relative";
    details.classList.remove("preview-container");
    details.classList.add("bt_image_container");
    var image_div = document.createElement("div");
    image_div.classList.add("bt_image_container");
    var image = document.createElement("img");
    image.classList.add("bt_image");
    image.src = details.getAttribute("data-url");
    image.style.opacity = 1;
    image_div.appendChild(image);
    details.appendChild(image_div);
    image.style.maxWidth = "100%";
    image.style.maxHeight = "600px";
    image.style.width = "auto";
    image.style.height = "100%";
    image.addEventListener("mousedown", (event) => {
      if (event.which != "1") {
        return; // no right click
      }
      resize(image, event); //set size first
      image.classList.add("image_resized");
    });
  });

  //Thread images
  var thread_images = document.querySelectorAll("div#post div.image");
  [...thread_images].forEach( (image) => {
    var a = image.querySelector("a");
    a.addEventListener("click", (event) => {
      event.preventDefault();
    });
    var img = image.querySelector("a img");
    img.addEventListener("mousedown", (event) => {
      if (event.which != "1") {
        return; // no right click
      }
      resize(img, event);
      img.classList.add("image_draggable");
    });
  });

  dispatch_event("after_image_resizer");
}

function navigator() {
  if (GM_getValue("navigator") != true) {
    return false;
  }
  dispatch_event("before_navigator");
  var morelinks = document.querySelector(".view-more-links");

  var navigator_container = document.createElement("span");
  navigator_container.id = "header_navigator_container";

  if (morelinks != null) {
    var links = document.querySelectorAll(".view-more-links a");
    var prev = document.createElement("span");
    prev.classList.add("header_bracket");
    var next = document.createElement("span");
    next.classList.add("header_bracket");
    if (links.length > 1) {
      prev.innerHTML = "[<a href='"+links[0].getAttribute('href')+"'>Prev</a>]";
      next.innerHTML = "[<a href='"+links[1].getAttribute('href')+"'>Next</a>]";
    } else {
      prev.innerHTML = "[Prev]";
      next.innerHTML = "[<a href='"+links[0].getAttribute('href')+"'>Next</a>]";
    }
    navigator_container.appendChild(prev);
    navigator_container.appendChild(next);
  }
  header_left.appendChild(navigator_container);
  dispatch_event("during_navigator");
}

function bottom_link() { // Run after document_loaded
  dispatch_event("before_bottom_link");
  document.querySelector("footer").id = "bottom";
  dispatch_event("after_bottom_link");
}

function create_toggle(config_name) {
  var _toggle = config[config_name];

  var _li = document.createElement("li");
  _li.id = "pref_li_"+config_name+"";

  var _checkbox = document.createElement("input");
  _checkbox.id = "pref_check_"+config_name+"";
  _checkbox.setAttribute("type", "checkbox");
  _li.appendChild(_checkbox);

  if (GM_getValue(config_name) == true) {
    _checkbox.checked = true;
  }

  GM_addValueChangeListener(""+config_name+"", function(key, old_val, new_val, remote) {
    if (arguments[2] == true) {
      _checkbox.checked = true;
    } else {
      _checkbox.checked = false;
    }
    log("Set GM Value "+config_name+" to "+arguments[2]+".");
  });

  _checkbox.addEventListener("change", (event) => {
    if (_checkbox.checked == true) {
      GM_setValue(""+config_name+"", true);
    } else {
      GM_setValue(""+config_name+"", false);
    }
    log("Set "+config_name+" config checkbox to "+_checkbox.checked+".");
  });

  var _label = document.createElement("label");
  _label.id = "pref_label_"+config_name+"";
  _label.setAttribute("for", _checkbox.id);
  var _a = document.createElement("a");
  _a.textContent = _toggle["name"];
  _label.appendChild(_a);
  _li.appendChild(_label);

  var _desc = document.createElement("span");
  _desc.id = "pref_desc_"+config_name+"";
  _desc.textContent = _toggle["desc"];
  _li.appendChild(_desc);

  return _li;
}

function open_preferences() {

  if (pref_container != false) {
    if (pref_container.style.display != "block") {
      dispatch_event("before_show_preferences");
      pref_container.style.display = "block";
      dispatch_event("after_show_preferences");
    } else {
      hide_preferences();
    }
    return false;
  }

  dispatch_event("before_open_preferences");
  pref_container = document.createElement("div");
  pref_container.id = "pref_container";
  pref_container.style.display = "block";

  var pref_backdrop = document.createElement("div");
  pref_backdrop.id = "pref_backdrop";
  pref_backdrop.addEventListener("click", hide_preferences);
  pref_container.appendChild(pref_backdrop);

  var pref_preferences = document.createElement("div");
  pref_preferences.id = "pref_preferences";

  var pref_nav_container = document.createElement("div");
  pref_nav_container.id = "pref_nav_container";

  var pref_nav = document.createElement("span");
  pref_nav.id = "pref_nav";
  pref_nav.innerHTML = `
    <span tab="general" selected=""><a>General</a></span>
    <span tab="style"><a>Style</a></span>
  `;
  pref_nav_container.appendChild(pref_nav);

  var pref_nav_right = document.createElement("span");
  pref_nav_right.id = "pref_nav_right";
  pref_nav_right.innerHTML = `
    <span tab="storage"><a>Storage</a></span>
  `;
  pref_nav_container.appendChild(pref_nav_right);

  var pref_close = document.createElement("span");
  pref_close.id = "pref_close";
  pref_close.innerHTML = `<a aria-label="Close Preferences">×</a>`;
  pref_close.addEventListener("click", hide_preferences);
  pref_nav_container.appendChild(pref_close);

  pref_preferences.appendChild(pref_nav_container);

  var pref_content = document.createElement("div");
  pref_content.id = "pref_content";
  // TABS IN HERE

  var general_tab = document.createElement("div");
  general_tab.id = "pref_general_content";
  general_tab.setAttribute("tab", "general");
  pref_content.appendChild(general_tab);

    //IMAGES
  var pref_images_fieldset = document.createElement("fieldset");
  pref_images_fieldset.id = "pref_images_fieldset";
  general_tab.appendChild(pref_images_fieldset);
  var pref_images_legend = document.createElement("legend");
  pref_images_legend.textContent = "Images";
  pref_images_fieldset.appendChild(pref_images_legend);
  var pref_images_ul = document.createElement("ul");
  pref_images_fieldset.appendChild(pref_images_ul);
  pref_images_ul.appendChild( create_toggle("expand_images") );
  pref_images_ul.appendChild( create_toggle("auto_expand_images") );
  pref_images_ul.appendChild( create_toggle("image_resizer") );
    //NAVIGATION
  var pref_navigation_fieldset = document.createElement("fieldset");
  pref_navigation_fieldset.id = "pref_navigation_fieldset";
  general_tab.appendChild(pref_navigation_fieldset);
  var pref_navigation_legend = document.createElement("legend");
  pref_navigation_legend.textContent = "Navigation";
  pref_navigation_fieldset.appendChild(pref_navigation_legend);
  var pref_navigation_ul = document.createElement("ul");
  pref_navigation_fieldset.appendChild(pref_navigation_ul);
  pref_navigation_ul.appendChild( create_toggle("navigator") );
    //MISCELLANEOUS
  var pref_misc_fieldset = document.createElement("fieldset");
  pref_misc_fieldset.id = "pref_misc_fieldset";
  general_tab.appendChild(pref_misc_fieldset);
  var pref_misc_legend = document.createElement("legend");
  pref_misc_legend.textContent = "Miscellaneous";
  pref_misc_fieldset.appendChild(pref_misc_legend);
  var pref_misc_ul = document.createElement("ul");
  pref_misc_fieldset.appendChild(pref_misc_ul);
  pref_misc_ul.appendChild( create_toggle("forced_anonymous") );
  pref_misc_ul.appendChild( create_toggle("hide_points") );
  pref_misc_ul.appendChild( create_toggle("hide_user_flair") );
  pref_misc_ul.appendChild( create_toggle("hide_submission_flair") );
  pref_misc_ul.appendChild( create_toggle("unbranding") );
  pref_misc_ul.appendChild( create_toggle("event_mode") );
  pref_misc_ul.appendChild( create_toggle("debug_mode") );

  pref_preferences.appendChild(pref_content);
  pref_container.appendChild(pref_preferences);

  dispatch_event("during_open_preferences");
  document.body.appendChild(pref_container);

  /*window.addEventListener("create_new_tab", (event) => {
    //event.detail
  });
  window.addEventListener("create_new_toggle", (event) => {
    //event.detail.name, event.detail.tab, event.detail.fieldset
    var tab = document.getElementById("pref_"+event.detail.tab+"_content");
    var fieldset = document.getElementById("pref_"+event.detail.fieldset+"_fieldset");
    var ul = fieldset.querySelector("ul");
    ul.appendChild( create_toggle("user_ids") );
  });*/ // actually this was a really cool unfinished idea to reuse code, but would need to replace GM with localstorage to share values with other scripts

  dispatch_event("after_open_preferences");
}

function hide_preferences() {
  dispatch_event("before_hide_preferences")
  pref_container.style.display = "none";
  dispatch_event("after_hide_preferences");
}

function preferences_button() {
  dispatch_event("before_preferences_button");
  pref_button = document.createElement("span");
  pref_button.id = "pref_button";
  pref_button.classList.add("header_bracket");
  pref_button.innerHTML = `
    [<a href="javascript:void">Config</a>]
  `;
  pref_button.addEventListener("click", () => {
    open_preferences();
  });
  header_right.appendChild(pref_button);
  dispatch_event("after_preferences_button");
}

dispatch_event("before_document_loaded");

document.addEventListener('DOMContentLoaded', (event) => {
  dispatch_event("during_document_loaded");
  // START NATIVE ONDOMLOAD FUNCTIONS
  add_style();
  create_header();
  open_preferences();
  hide_preferences();
  preferences_button();
  bottom_link();
  user_tag();
  move_links();
  move_details();

  expand_images_button();
  auto_expand_images();
  image_resizer();
  navigator();
  forced_anonymous();
  hide_points();
  hide_user_flair();
  hide_submission_flair();
  unbranding();
  // ENDOF NATIVE ONDOMLOAD FUNCTIONS

  dispatch_event("after_document_loaded");
  dispatch_event("after_startup");
  log("End of Script");
});

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址