AO3: [Wrangling] Show fandoms in Tag Search!

Show a tag's fandom and it's synned/unsynned status in the tag search results!!

当前为 2022-06-14 提交的版本,查看 最新版本

// ==UserScript==
// @name         AO3: [Wrangling] Show fandoms in Tag Search!
// @description  Show a tag's fandom and it's synned/unsynned status in the tag search results!!
// @version      1.0.1

// @author       owlwinter
// @namespace    N/A
// @license      MIT license

// @match        *://*.archiveofourown.org/tags/search?*
// @grant        none
// ==/UserScript==


(function() {
    'use strict';

    const array = a => Array.prototype.slice.call(a, 0)

    // called for each tag in the search results list
    // `url` is the url of the edit tag page
    // `a` is the link, whose color we will change based on whether the tag is a symlink
    // `result` is the span with the "Loading..." in it where we will put the results of our request
    const get_fandoms = function get_fandoms(url, a, result) {
        const xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function xhr_onreadystatechange() {
            if (xhr.readyState == xhr.DONE ) {
                if (xhr.status == 200) {
                    // the "Loading..." text that we show while our script is running is in italics - so clear that
                    result.style.fontStyle = "";
                    // gets the fandoms of the tag
                    // does this by peerking at all the "fandoms to remove" on the tag's edit form and putting them into a list
                    const fandoms = []
                    const checks = array(xhr.responseXML.documentElement.querySelectorAll("label > input[name='tag[associations_to_remove][]']")).filter(foo => foo.id.indexOf("parent_Fandom_associations_to_remove") != -1);
                    for (const check of checks) {
                        const name = check.parentElement.nextElementSibling.innerText
                        fandoms.push(name)
                    }
                    // figure out the text to display based on whether there were any fandoms or not
                    const text = fandoms.length == 0 ? "Unwrangled" : fandoms.join(", ");
                    result.innerText = text;
                    // check if the tag is synned or not
                    const synned = xhr.responseXML.documentElement.querySelector("#tag_syn_string").value != ""
                    // if the tag is a synned, leave it alone, otherwise make it blue
                    a.style.color = synned ? "" : "#00C";
                    // hovering over a blue link defaults to a purple background that is just totally unreadable, this class
                    // makes the hover background color white instead
                    if (!synned) {
                        a.classList.toggle("not_synned")
                    }
                } else if (xhr.status == 429) {
                    // ~ao3jail
                    result.innerText = "Rate limited. Sorry :("
                } else {
                    result.innerText = "Unexpected error, check the console"
                    console.log(xhr)
                }
            }
        }
        xhr.open("GET", url)
        xhr.responseType = "document"
        xhr.send()
    }

    const button = document.createElement("button")

    const do_thing = function do_thing(e) {
        e.preventDefault()
        // find each item in the tag search results list
        const search_results = document.querySelector("#main > ol.tag.index.group").getElementsByClassName("tag")
        for (const a of search_results) {
            const span = a.parentElement;
            const dash = document.createTextNode(" - ");
            span.appendChild(dash);
            // this is the span that will hold the result when the request finishes
            const loading = document.createElement("span");
            //Before our request finishes, shows a loading text so user knows something is happening
            loading.innerText = "Loading..."
            loading.style.fontStyle = "italic"
            span.appendChild(dash);
            span.appendChild(loading);
            // trigger xhr (asynchronous)
            get_fandoms(a.href + "/edit", a, loading);
        }
        // add the unsynned color explanation text to the top of the page, replacing the button
        const div = document.createElement("div")
        div.style.fontSize = "0.875rem"
        div.style.fontStyle = "italic"
        div.appendChild(document.createTextNode(""))
        const span = document.createElement("span")
        span.style.color = "#00C"
        span.innerText = "Blue"
        div.appendChild(span)
        div.appendChild(document.createTextNode(" means tag is not synned"))
        div.style.marginTop = "10px"
        button.parentElement.appendChild(div)
        button.parentElement.removeChild(button)
    }

    // Adds the load fandom button - since this can get someone rate limited,
    // we definitely don't want to have it happen automatically
    button.innerText = "Load fandoms"
    button.addEventListener("click", do_thing)
    button.style.display = "block"
    button.style.fontSize = "0.627rem"
    button.style.marginTop = "10px"

    document.querySelector("#main > h3").append(button)

    // removes the color background color of the not synned tags are when the user's cursor hovers over them
    // trust me, keeping the same magenta but with the blue text was atrocious
    // comment out the next three lines out at your own risk
    // ......you really don't want to
    // .........don't say i didn't warn you....,
    const style = document.createElement("style")
    style.innerHTML = ".not_synned:hover { background-color: white !important; }"
    document.head.appendChild(style)
})();