AO3: Tag counter when posting/editing works

Count number of tags that count towards the 75 limit on works

  1. // ==UserScript==
  2. // @name AO3: Tag counter when posting/editing works
  3. // @namespace https://github.com/RhineCloud
  4. // @version 1.0.1
  5. // @description Count number of tags that count towards the 75 limit on works
  6. // @grant none
  7. // @author Rhine
  8. // @match https://*.archiveofourown.org/works/new*
  9. // @include /https?:\/\/[^\/]*archiveofourown.org\/works\/[0-9]+\/edit(_tags)?\/?/
  10. // @license GPL-3.0 <https://www.gnu.org/licenses/gpl.html>
  11. // ==/UserScript==
  12.  
  13. // CSS settings
  14. // unknown: at the beginning, before tags were added or counted
  15. const style_unknown = 'background: #999;';
  16. // ok: at least 1 fandom tag, but still within the tag limit
  17. const style_ok = 'background: #099;';
  18. // warning: more than 75 tags that count towards the limit
  19. const style_warning = 'background: #900;';
  20.  
  21.  
  22. // counter to track the number of fandom, relationship, character, and additional tags
  23. const tag_counts = [0, 0, 0, 0];
  24.  
  25. function update_tag_counts() {
  26. // grab relevant fields of the work posting/editing form
  27. const fandoms = document.querySelector('#work-form .work.meta dd.fandom .autocomplete');
  28. const relationships = document.querySelector('#work-form .work.meta dd.relationship .autocomplete');
  29. const characters = document.querySelector('#work-form .work.meta dd.character .autocomplete');
  30. const freeforms = document.querySelector('#work-form .work.meta dd.freeform .autocomplete');
  31.  
  32. // count properly added tags above the input field
  33. tag_counts[0] = fandoms.querySelectorAll('li.added.tag').length;
  34. tag_counts[1] = relationships.querySelectorAll('li.added.tag').length;
  35. tag_counts[2] = characters.querySelectorAll('li.added.tag').length;
  36. tag_counts[3] = freeforms.querySelectorAll('li.added.tag').length;
  37.  
  38. // count the number of tags still in the input fields proper
  39. tag_counts[0] += fandoms.querySelector('input').value.split(/[,,、]/).filter(value => value.trim()).length;
  40. tag_counts[1] += relationships.querySelector('input').value.split(/[,,、]/).filter(value => value.trim()).length;
  41. tag_counts[2] += characters.querySelector('input').value.split(/[,,、]/).filter(value => value.trim()).length;
  42. tag_counts[3] += freeforms.querySelector('input').value.split(/[,,、]/).filter(value => value.trim()).length;
  43. }
  44.  
  45. // sum up the counts from each relevant tag category
  46. function get_total_count() {
  47. return tag_counts.reduce((prev_count, curr_count) => prev_count + curr_count, 0);
  48. }
  49.  
  50. // check if the total tag count total is within the tag limit
  51. function is_within_limits() {
  52. return 75 >= get_total_count();
  53. }
  54.  
  55. // insert the counter on the page
  56. const style_counter = 'position: fixed; right: 0; bottom: 2em; z-index: 10;';
  57. const fieldset_counter = document.createElement('fieldset');
  58. fieldset_counter.innerHTML = '<legend>Tag Counter</legend>' +
  59. '<h3 class="landmark heading">Tag Counter</h3>' +
  60. '<dl>' +
  61. '<dt>Fandoms</dt>' +
  62. '<dd id="fandom_tag_count">?</dd>' +
  63. '<dt>Relationships</dt>' +
  64. '<dd id="relationship_tag_count">?</dd>' +
  65. '<dt>Characters</dt>' +
  66. '<dd id="character_tag_count">?</dd>' +
  67. '<dt>Additional Tags</dt>' +
  68. '<dd id="freeform_tag_count">?</dd>' +
  69. '<dt style="font-weight: bolder;">Total</dt>' +
  70. '<dd id="total_tag_count" style="font-weight: bolder;">?</dd>' +
  71. '</dl>' +
  72. '<button id="update_tag_counter" type="button">Update Counter</button>';
  73. fieldset_counter.setAttribute('style', style_counter + style_unknown);
  74. document.querySelector('#work-form').prepend(fieldset_counter);
  75.  
  76. // update the counter on the page when the button is clicked
  77. fieldset_counter.querySelector('#update_tag_counter').addEventListener('click', () => {
  78. update_tag_counts();
  79. fieldset_counter.querySelector('#fandom_tag_count').innerText = tag_counts[0];
  80. fieldset_counter.querySelector('#relationship_tag_count').innerText = tag_counts[1];
  81. fieldset_counter.querySelector('#character_tag_count').innerText = tag_counts[2];
  82. fieldset_counter.querySelector('#freeform_tag_count').innerText = tag_counts[3];
  83. fieldset_counter.querySelector('#total_tag_count').innerText = get_total_count();
  84. // update colour scheme
  85. if (0 === tag_counts[0]) {
  86. fieldset_counter.setAttribute('style', style_counter + style_unknown);
  87. } else if (is_within_limits()) {
  88. fieldset_counter.setAttribute('style', style_counter + style_ok);
  89. } else {
  90. fieldset_counter.setAttribute('style', style_counter + style_warning);
  91. }
  92. });