// ==UserScript==
// @name AO3: [Wrangling] Edit Tag page cleanup
// @namespace https://greasyfork.org/en/users/906106-escctrl
// @description Removes descriptions and some fields from Edit Tag pages to avoid wrangling accidents
// @author escctrl
// @version 4.4.1
// @match *://*.archiveofourown.org/tags/*/edit
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js
// @license MIT
// ==/UserScript==
(function($) {
'use strict';
// remove all descriptions to save space. experienced wranglers know them by heart
$('form#edit_tag dl dd p').not('.actions').hide();
// store commonly referred to IDs to reduce DOM traversal, use JS instead of jQuery to speed it up
const fieldCanonical = document.getElementById('tag_canonical');
const fieldUnwrangleable = document.getElementById('tag_unwrangleable');
const fieldSynonym = document.getElementById('tag_syn_string');
// what's the status of my tag?
const is_canonical = fieldCanonical.checked == true ? true : false;
const is_unwrangleable = fieldUnwrangleable.checked == true ? true : false;
const is_synonym = ($(fieldSynonym).prev().find("li.added").length == 1) ? true : false;
// if the tag is two things at once, something was already incorrect, and we'd rather display all fields again to allow fixing it
if (is_canonical && (is_unwrangleable || is_synonym) || (is_unwrangleable && is_synonym)) { return false; }
// if the tag is not canonical, remove the metatag field
if (!is_canonical) {
$('dd[title="MetaTags"]').hide().prev().hide();
}
if (is_canonical) {
// remove the unwrangleable button
hide_fields(false, true, false);
// disable the canonical checkbox if there is a metatag (to avoid the filter bug)
if ($('#parent_MetaTag_associations_to_remove_checkboxes').length == 1) {
$(fieldCanonical).attr("disabled", "disabled");
$('input[name="tag[canonical]"]').attr("disabled", "disabled");
}
// remove the Add Subtags and Add Synonyms fields
// if you don't want this, disable it by just adding // at the beginning of the next line
hide_addsubsyn();
}
else if (is_synonym) {
// remove the canonical and unwrangleable button
hide_fields(true, true, false);
// make the canonical tag itself an edit link like all other referenced tags on this page. then the Edit button can be removed
var taglink = $(fieldSynonym).siblings('p.actions').hide().find('a').attr("href");
$(fieldSynonym).siblings('ul.autocomplete').find('li.added').contents().first().wrap('<a class="tag" href="'+taglink+'"></a>');
}
else if (is_unwrangleable) {
// remove canonical button and synonym field
hide_fields(true, false, true);
}
else {
document.getElementById('tag_syn_string_autocomplete').focus();
}
// if the tag is draft only, highlight the Draft field big and bright
const taggings = [];
// retrieve the numbers showing in the sidebar. we only need ones that are not linked (drafts, private bookmarks, total taggings)
$('#dashboard.tag.wrangling ul:nth-of-type(2) li span').each( function() {
// we grab the text, match only the number in it, convert it from string to int, and add it to the array
taggings.push(parseInt($(this).text().match(/\d+/g)));
});
// [0] is drafts, [2] is the total taggings count. if they are equal, the tag is draft only
// we check that total taggings are more than zero, or we'd end up highlighting every zero-taggings draft as well (zero drafts == zero total uses)
if (taggings[0] == taggings[2] && taggings[2] > 0) {
// Checks if using a dark mode by calculating the 'brightness' of the page background color
const drafthighlight = lightOrDark(window.getComputedStyle(document.body).backgroundColor) == "dark" ? '#a08b2c' : 'yellow' ;
$('#dashboard.tag.wrangling ul:nth-of-type(2) li:nth-of-type(2) span')
.css('background-color', drafthighlight)
.attr('title',"This tag is still in draft, you don't need to wrangle it yet");
}
// CONVENIENCE FUNCTIONS
// hides the canonical/unwrangled checkboxes and synonym field
function hide_fields(c, u, s) {
if (c) { $(fieldCanonical).parent().hide().prev().hide(); }
if (u) { $(fieldUnwrangleable).parent().hide().prev().hide(); }
if (s) { $(fieldSynonym).parent().hide().prev().hide(); }
}
// hides the "add subtag" and "add synonym" fields - or the whole line if no sub/syn tags exist to save space
function hide_addsubsyn() {
var add_sub = $('dt').filter(() => $(this).text() == "SubTags");
if ($('#child_SubTag_associations_to_remove_checkboxes').length == 0) add_sub.hide().next().hide();
else add_sub.next().children('div[title="add tags"],h5.heading').hide();
var add_syn = $('dt').filter(() => $(this).text() == "Synonyms");
if ($('#child_Merger_associations_to_remove_checkboxes').length == 0) add_syn.hide().next().hide();
else add_syn.next().children('div[title="add tags"],h5.heading').hide();
// if there are neither subtags nor synonyms to display, hide the whole Child Tags fieldset
if ($('#child_SubTag_associations_to_remove_checkboxes').length == 0 && $('#child_Merger_associations_to_remove_checkboxes').length == 0) {
add_sub.parent().parent().hide();
}
}
})(jQuery);
// helper function to determine whether a color (the background in use) is light or dark
// https://awik.io/determine-color-bright-dark-using-javascript/
function lightOrDark(color) {
// Variables for red, green, blue values
var r, g, b, hsp;
// Check the format of the color, HEX or RGB?
if (color.match(/^rgb/)) {
// If RGB --> store the red, green, blue values in separate variables
color = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
r = color[1];
g = color[2];
b = color[3];
}
else {
// If hex --> Convert it to RGB: http://gist.github.com/983661
color = +("0x" + color.slice(1).replace(
color.length < 5 && /./g, '$&$&'));
r = color >> 16;
g = color >> 8 & 255;
b = color & 255;
}
// HSP (Highly Sensitive Poo) equation from http://alienryderflex.com/hsp.html
hsp = Math.sqrt( 0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b) );
// Using the HSP value, determine whether the color is light or dark
if (hsp>127.5) { return 'light'; }
else { return 'dark'; }
}