ChatGPT Character Counter

Adds a character counter to message fields on chatgpt.com

  1. // ==UserScript==
  2. // @name ChatGPT Character Counter
  3. // @namespace https://leaked.tools/
  4. // @version 1.4
  5. // @description Adds a character counter to message fields on chatgpt.com
  6. // @author Sango
  7. // @match *://chatgpt.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=chatgpt.com
  9. // @license MIT
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15.  
  16. const maxCharacters = 32732;
  17.  
  18. function addCharacterCounter(element, position) {
  19. // Avoid adding multiple counters to the same element
  20. if (position.previousElementSibling && position.previousElementSibling.classList.contains('character-counter')) {
  21. return;
  22. }
  23.  
  24. // Create the counter element
  25. const counter = document.createElement('div');
  26. counter.className = 'character-counter flex items-center justify-center';
  27. counter.style.fontSize = '14px';
  28. counter.style.color = '#555';
  29. counter.style.marginRight = '5px';
  30. counter.textContent = `0/${maxCharacters}`;
  31.  
  32. // Insert the counter before the element
  33. position.insertAdjacentElement('beforebegin', counter);
  34.  
  35. // Update the counter when the content changes
  36. const updateCounter = () => {
  37. const content = element.value || element.textContent.trim();
  38. const currentLength = content.length;
  39. counter.textContent = `${currentLength}/${maxCharacters}`;
  40.  
  41. // Change color if limit exceeded
  42. if (currentLength > maxCharacters) {
  43. counter.style.color = '#ffa700';
  44. } else {
  45. counter.style.color = '#555';
  46. }
  47. };
  48.  
  49. // Listen for content changes
  50. if (element.tagName.toLowerCase() === 'textarea') {
  51. element.addEventListener('keyup', updateCounter);
  52. } else {
  53. const observer = new MutationObserver(updateCounter);
  54. observer.observe(element, { childList: true, subtree: true, characterData: true });
  55. }
  56.  
  57. updateCounter(); // Initialize the counter
  58. }
  59.  
  60.  
  61. function observeFields() {
  62. const observer = new MutationObserver(() => {
  63. const editableDivs = document.querySelectorAll('div[contenteditable="true"]');
  64. editableDivs.forEach((editableDiv) => {
  65. if (!editableDiv.dataset.counterAdded) {
  66. editableDiv.dataset.counterAdded = true; // Mark this div as processed
  67. addCharacterCounter(editableDiv, editableDiv.parentElement.parentElement.parentElement.parentElement.querySelector(".flex.gap-x-1:last-of-type>.min-w-8"));
  68. }
  69. });
  70.  
  71. const textareas = document.querySelectorAll('textarea:not([placeholder="Message ChatGPT"])');
  72. textareas.forEach((textarea) => {
  73. if (!textarea.dataset.counterAdded) {
  74. textarea.dataset.counterAdded = true; // Mark this textarea as processed
  75. addCharacterCounter(textarea, textarea.parentElement.parentElement.parentElement.querySelector(".flex.justify-end>.btn"));
  76. }
  77. });
  78. });
  79.  
  80. observer.observe(document.body, { childList: true, subtree: true });
  81. }
  82.  
  83. observeFields();
  84. })();

QingJ © 2025

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