AO3: [Wrangling] Edit Tag page cleanup

Removes descriptions and some fields from Edit Tag pages to avoid wrangling accidents

目前为 2022-08-01 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name AO3: [Wrangling] Edit Tag page cleanup
  3. // @namespace https://greasyfork.org/en/users/906106-escctrl
  4. // @description Removes descriptions and some fields from Edit Tag pages to avoid wrangling accidents
  5. // @author escctrl
  6. // @version 4.3
  7. // @match *://*.archiveofourown.org/tags/*/edit
  8. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function($) {
  13. 'use strict';
  14.  
  15. // remove all descriptions to save space. experienced wranglers know them by heart
  16. $('form#edit_tag dl dd p').not('.actions').hide();
  17.  
  18. // store commonly referred to IDs to reduce DOM traversal, use JS instead of jQuery to speed it up
  19. const fieldCanonical = document.getElementById('tag_canonical');
  20. const fieldUnwrangleable = document.getElementById('tag_unwrangleable');
  21. const fieldSynonym = document.getElementById('tag_syn_string');
  22.  
  23. // what's the status of my tag?
  24. const is_canonical = fieldCanonical.checked == true ? true : false;
  25. const is_unwrangleable = fieldUnwrangleable.checked == true ? true : false;
  26. const is_synonym = ($(fieldSynonym).prev().find("li.added").length == 1) ? true : false;
  27.  
  28. // if the tag is two things at once, something was already incorrect, and we'd rather display all fields again to allow fixing it
  29. if (is_canonical && (is_unwrangleable || is_synonym) || (is_unwrangleable && is_synonym)) { return false; }
  30.  
  31.  
  32. // if the tag is not canonical, remove the metatag field
  33. if (!is_canonical) {
  34. $('dd[title="MetaTags"]').hide().prev().hide();
  35. }
  36.  
  37. if (is_canonical) {
  38. // remove the unwrangleable button
  39. hide_fields(false, true, false);
  40.  
  41. // disable the canonical checkbox if there is a metatag (to avoid the filter bug)
  42. if ($('#parent_MetaTag_associations_to_remove_checkboxes').length == 1) {
  43. $(fieldCanonical).attr("disabled", "disabled");
  44. $('input[name="tag[canonical]"]').attr("disabled", "disabled");
  45. }
  46.  
  47. // remove the Add Subtags and Add Synonyms fields
  48. // if you don't want this, disable it by just adding // at the beginning of the next line
  49. hide_addsubsyn();
  50. }
  51. else if (is_synonym) {
  52. // remove the canonical and unwrangleable button
  53. hide_fields(true, true, false);
  54.  
  55. // make the canonical tag itself an edit link like all other referenced tags on this page. then the Edit button can be removed
  56. var taglink = $(fieldSynonym).siblings('p.actions').hide().find('a').attr("href");
  57. $(fieldSynonym).siblings('ul.autocomplete').find('li.added').contents().first().wrap('<a class="tag" href="'+taglink+'"></a>');
  58. }
  59. else if (is_unwrangleable) {
  60. // remove canonical button and synonym field
  61. hide_fields(true, false, true);
  62. }
  63. else {
  64. document.getElementById('tag_syn_string_autocomplete').focus();
  65. }
  66.  
  67. // if the tag is draft only, highlight the Draft field big and bright
  68. const taggings = [];
  69.  
  70. // retrieve the numbers showing in the sidebar. we only need ones that are not linked (drafts, private bookmarks, total taggings)
  71. $('#dashboard.tag.wrangling ul:nth-of-type(2) li span').each( function() {
  72. // we grab the text, match only the number in it, convert it from string to int, and add it to the array
  73. taggings.push(parseInt($(this).text().match(/\d+/g)));
  74. });
  75.  
  76. // [0] is drafts, [2] is the total taggings count. if they are equal, the tag is draft only
  77. // 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)
  78. if (taggings[0] == taggings[2] && taggings[2] > 0) {
  79.  
  80. // Checks if using a dark mode by calculating the 'brightness' of the page background color
  81. const drafthighlight = lightOrDark(window.getComputedStyle(document.body).backgroundColor) == "dark" ? '#a08b2c' : 'yellow' ;
  82.  
  83. $('#dashboard.tag.wrangling ul:nth-of-type(2) li:nth-of-type(2) span')
  84. .css('background-color', drafthighlight)
  85. .attr('title',"This tag is still in draft, you don't need to wrangle it yet");
  86. }
  87.  
  88. // CONVENIENCE FUNCTIONS
  89.  
  90. // hides the canonical/unwrangled checkboxes and synonym field
  91. function hide_fields(c, u, s) {
  92. if (c) { $(fieldCanonical).parent().hide().prev().hide(); }
  93. if (u) { $(fieldUnwrangleable).parent().hide().prev().hide(); }
  94. if (s) { $(fieldSynonym).parent().hide().prev().hide(); }
  95. }
  96.  
  97. // hides the "add subtag" and "add synonym" fields - or the whole line if no sub/syn tags exist to save space
  98. function hide_addsubsyn() {
  99. var add_sub = $('dt').filter(function() {
  100. return $(this).text() == "SubTags";
  101. });
  102. if ($('#child_SubTag_associations_to_remove_checkboxes').length == 0) {
  103. add_sub.hide().next().hide();
  104. }
  105. else {
  106. add_sub.next().children('div[title="add tags"],h5.heading').hide();
  107. }
  108.  
  109. var add_syn = $('dt').filter(function() {
  110. return $(this).text() == "Synonyms";
  111. });
  112. if ($('#child_Merger_associations_to_remove_checkboxes').length == 0) {
  113. add_syn.hide().next().hide();
  114. }
  115. else {
  116. add_syn.next().children('div[title="add tags"],h5.heading').hide();
  117. }
  118. }
  119.  
  120. })(jQuery);
  121.  
  122. // helper function to determine whether a color (the background in use) is light or dark
  123. // https://awik.io/determine-color-bright-dark-using-javascript/
  124. function lightOrDark(color) {
  125.  
  126. // Variables for red, green, blue values
  127. var r, g, b, hsp;
  128.  
  129. // Check the format of the color, HEX or RGB?
  130. if (color.match(/^rgb/)) {
  131. // If RGB --> store the red, green, blue values in separate variables
  132. color = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
  133.  
  134. r = color[1];
  135. g = color[2];
  136. b = color[3];
  137. }
  138. else {
  139. // If hex --> Convert it to RGB: http://gist.github.com/983661
  140. color = +("0x" + color.slice(1).replace(
  141. color.length < 5 && /./g, '$&$&'));
  142.  
  143. r = color >> 16;
  144. g = color >> 8 & 255;
  145. b = color & 255;
  146. }
  147.  
  148. // HSP (Highly Sensitive Poo) equation from http://alienryderflex.com/hsp.html
  149. hsp = Math.sqrt( 0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b) );
  150.  
  151. // Using the HSP value, determine whether the color is light or dark
  152. if (hsp>127.5) { return 'light'; }
  153. else { return 'dark'; }
  154. }