ChatGPT Character Counter

Adds a character counter to message fields on chatgpt.com

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         ChatGPT Character Counter
// @namespace    https://leaked.tools/
// @version      1.4
// @description  Adds a character counter to message fields on chatgpt.com
// @author       Sango
// @match        *://chatgpt.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=chatgpt.com
// @license      MIT
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const maxCharacters = 32732;

function addCharacterCounter(element, position) {
    // Avoid adding multiple counters to the same element
    if (position.previousElementSibling && position.previousElementSibling.classList.contains('character-counter')) {
        return;
    }

    // Create the counter element
    const counter = document.createElement('div');
    counter.className = 'character-counter flex items-center justify-center';
    counter.style.fontSize = '14px';
    counter.style.color = '#555';
    counter.style.marginRight = '5px';
    counter.textContent = `0/${maxCharacters}`;

    // Insert the counter before the element
    position.insertAdjacentElement('beforebegin', counter);

    // Update the counter when the content changes
    const updateCounter = () => {
        const content = element.value || element.textContent.trim();
        const currentLength = content.length;
        counter.textContent = `${currentLength}/${maxCharacters}`;

        // Change color if limit exceeded
        if (currentLength > maxCharacters) {
            counter.style.color = '#ffa700';
        } else {
            counter.style.color = '#555';
        }
    };

    // Listen for content changes
    if (element.tagName.toLowerCase() === 'textarea') {
        element.addEventListener('keyup', updateCounter);
    } else {
        const observer = new MutationObserver(updateCounter);
        observer.observe(element, { childList: true, subtree: true, characterData: true });
    }

    updateCounter(); // Initialize the counter
}


    function observeFields() {
        const observer = new MutationObserver(() => {
            const editableDivs = document.querySelectorAll('div[contenteditable="true"]');
            editableDivs.forEach((editableDiv) => {
                if (!editableDiv.dataset.counterAdded) {
                    editableDiv.dataset.counterAdded = true; // Mark this div as processed
                    addCharacterCounter(editableDiv, editableDiv.parentElement.parentElement.parentElement.parentElement.querySelector(".flex.gap-x-1:last-of-type>.min-w-8"));
                }
            });

            const textareas = document.querySelectorAll('textarea:not([placeholder="Message ChatGPT"])');
            textareas.forEach((textarea) => {
                if (!textarea.dataset.counterAdded) {
                    textarea.dataset.counterAdded = true; // Mark this textarea as processed
                    addCharacterCounter(textarea, textarea.parentElement.parentElement.parentElement.querySelector(".flex.justify-end>.btn"));
                }
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });
    }

    observeFields();
})();