TTV

Công cụ đăng chương hiện đại cho Tàng Thư Viện với UI/UX được tối ưu

2025-03-07 या दिनांकाला. सर्वात नवीन आवृत्ती पाहा.

// ==UserScript==
// @name         TTV
// @namespace    http://tampermonkey.net/
// @version      7.2
// @description  Công cụ đăng chương hiện đại cho Tàng Thư Viện với UI/UX được tối ưu
// @author       HA
// @match        https://tangthuvien.net/dang-chuong/story/*
// @match        https://tangthuvien.net/danh-sach-chuong/story/*
// @grant        GM_addStyle
// @grant        GM_setValue 
// @grant        GM_getValue
// @required     https://code.jquery.com/jquery-3.2.1.min.js
// ==/UserScript==

(function() {
    'use strict';

    const headerSign = "";
    const footerSign = "";
    const MAX_CHAPTER_POST = 10;

    let CHAP_NUMBER = 1;
    let CHAP_STT = 1;
    let CHAP_SERIAL = 1;
    let CHAP_NUMBER_ORIGINAL = 1;
    let CHAP_STT_ORIGINAL = 1;
    let CHAP_SERIAL_ORIGINAL = 1;

    // CSS tùy chỉnh
    GM_addStyle(`
        #modern-uploader {
            position: fixed;
            top: 10px;
            right: 10px;
            width: 400px;
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
            z-index: 9999;
        }

        #notification-area {
            padding: 0.5rem;
            border-radius: 0.25rem;
            font-weight: bold;
        }

        .notification-success { color: #22c55e; }
        .notification-error { color: #ef4444; }
        .notification-warning { color: #f59e0b; }
        .notification-info { color: #3b82f6; }

        .loading-overlay {
            position: fixed;
            inset: 0;
            background: rgba(0, 0, 0, 0.5);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 9999;
        }

        .loading-spinner {
            width: 40px;
            height: 40px;
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3b82f6;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        #debug-output {
            font-family: monospace;
            white-space: pre;
            font-size: 12px;
            max-height: 200px;
            overflow: auto;
            margin-top: 10px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            background: #f5f5f5;
        }

        .character-counter {
            text-align: right;
            margin-top: 5px;
            font-size: 12px;
            color: #666;
        }
    `);

    // Tạo HTML cho chương mới
    function createChapterHTML(number) {
        const chap_vol = parseInt(jQuery('.chap_vol').val());
        const chap_vol_name = jQuery('.chap_vol_name').val();

        return `
            <div data-gen="MK_GEN" id="COUNT_CHAP_${number}_MK">
                <div class="col-xs-12 form-group"></div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_stt">STT</label>
                    <div class="col-sm-8">
                        <input class="form-control" required name="chap_stt[${number}]" value="${CHAP_STT}"
                            placeholder="Số thứ tự của chương" type="text"/>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_number">Chương thứ..</label>
                    <div class="col-sm-8">
                        <input value="${CHAP_SERIAL}" required class="form-control" name="chap_number[${number}]" 
                            placeholder="Chương thứ.. (1,2,3..)" type="text"/>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_name">Quyển số</label>
                    <div class="col-sm-8">
                        <input class="form-control" name="vol[${number}]" 
                            placeholder="Quyển số" type="number" value="${chap_vol}" required/>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_name">Tên quyển</label>
                    <div class="col-sm-8">
                        <input class="form-control chap_vol_name" name="vol_name[${number}]" 
                            placeholder="Tên quyển" type="text" value="${chap_vol_name}" />
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="chap_name">Tên chương</label>
                    <div class="col-sm-8">
                        <input required class="form-control" name="chap_name[${number}]" 
                            placeholder="Tên chương" type="text"/>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="introduce">Nội dung</label>
                    <div class="col-sm-8">
                        <textarea maxlength="75000" style="color:#000;font-weight: 400;" required class="form-control chapter-content"
                            name="introduce[${number}]" rows="20" placeholder="Nội dung" type="text"></textarea>
                        <div class="character-counter" style="text-align: right; margin-top: 5px; font-size: 12px; color: #666;">
                            <span class="current-count">0</span>/20.000 ký tự
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <label class="col-sm-2" for="adv">Quảng cáo</label>
                    <div class="col-sm-8">
                        <textarea maxlength="1000" class="form-control" name="adv[${number}]" 
                            placeholder="Quảng cáo" type="text"></textarea>
                    </div>
                </div>
            </div>`;
    }

    // Thêm chương mới
    function addNewChapter() {
        if ((CHAP_NUMBER + 1) <= MAX_CHAPTER_POST) {
            updateChapNumber(true);
            const html = createChapterHTML(CHAP_NUMBER);
            jQuery('#add-chap').before(html);
            setupCharacterCounter(); // Add this line to initialize counter for new chapters
        } else {
            showNotification(`Chỉ có thể đăng tối đa ${MAX_CHAPTER_POST} chương một lần`, 'warning');
        }
    }

    // Cập nhật số chương
    function updateChapNumber(isAdd) {
        try {
            if (isAdd) {
                let maxStt = 0;
                let maxSerial = 0;

                // Tìm giá trị lớn nhất trong tất cả các input hiện có
                jQuery('input[name^="chap_stt"]').each(function() {
                    const val = parseInt(jQuery(this).val()) || 0;
                    maxStt = Math.max(maxStt, val);
                });

                jQuery('input[name^="chap_number"]').each(function() {
                    const val = parseInt(jQuery(this).val()) || 0;
                    maxSerial = Math.max(maxSerial, val);
                });

                // So sánh với giá trị từ DOM
                const chapStt = parseInt(jQuery('.chap_stt1').val()) || 0;
                const chapSerial = parseInt(jQuery('.chap_serial').val()) || 0;

                maxStt = Math.max(maxStt, chapStt);
                maxSerial = Math.max(maxSerial, chapSerial);

                // Cập nhật biến đếm
                CHAP_STT = maxStt + 1;
                CHAP_SERIAL = maxSerial + 1;
                CHAP_NUMBER++;
            } else {
                if (CHAP_NUMBER > CHAP_NUMBER_ORIGINAL) {
                    CHAP_NUMBER--;
                }
                if (CHAP_STT > CHAP_STT_ORIGINAL) {
                    CHAP_STT--;
                }
                if (CHAP_SERIAL > CHAP_SERIAL_ORIGINAL) {
                    CHAP_SERIAL--;
                }
            }

            jQuery('#chap_number').val(CHAP_NUMBER);
            jQuery('#chap_stt').val(CHAP_STT);
            jQuery('#chap_serial').val(CHAP_SERIAL);
            jQuery('#countNumberPost').text(CHAP_NUMBER);
        } catch (e) {
            console.log("Lỗi: " + e);
        }
    }

    // Tạo giao diện chính
    function createInterface() {
        const container = document.createElement('div');
        container.id = 'modern-uploader';
        container.innerHTML = `
            <div class="text-center mb-4">
                <h3 class="text-xl font-bold">CÔNG CỤ ĐĂNG NHANH</h3>
                <p id="short-chapter-warning" class="text-red-500 mt-2 hidden"></p>
            </div>

            <div class="form-group">
                <textarea id="qpContent" class="form-control" rows="5" 
                    placeholder="Dán nội dung truyện vào đây để tự động tách chương"></textarea>
            </div>

            <div class="debug-info" style="display: none;">
                <pre id="debug-output"></pre>
            </div>

            <div class="flex justify-between">
                <button class="btn btn-outline" id="qpButtonRemoveEmpty">Xóa chương trống</button>
                <button class="btn btn-primary" id="qpButtonSubmit">Đăng chương</button>
            </div>

            <div id="notification-area" class="mt-3 text-center"></div>
        `;

        jQuery(".list-in-user").before(container);
        setupEventListeners();
    }

    // Khởi tạo các chương
    function initializeChapters() {
        showLoading();
        try {
            const chap_number = parseInt(jQuery('#chap_number').val());
            let chap_stt = parseInt(jQuery('.chap_stt1').val());
            let chap_serial = parseInt(jQuery('.chap_serial').val());

            if (parseInt(jQuery('#chap_stt').val()) > chap_stt) {
                chap_stt = parseInt(jQuery('#chap_stt').val());
            }
            if (parseInt(jQuery('#chap_serial').val()) > chap_serial) {
                chap_serial = parseInt(jQuery('#chap_serial').val());
            }

            CHAP_NUMBER = CHAP_NUMBER_ORIGINAL = chap_number;
            CHAP_STT = CHAP_STT_ORIGINAL = chap_stt;
            CHAP_SERIAL = CHAP_SERIAL_ORIGINAL = chap_serial;

            // Thêm 9 chương mới
            for(let i = 0; i < 9; i++) {
                addNewChapter();
            }

            hideLoading();
            showNotification('Đã tạo đủ 10 chương');
        } catch (e) {
            console.log("Lỗi: " + e);
            hideLoading();
            showNotification('Có lỗi khi tạo chương', 'error');
        }
    }

    // Khởi tạo các event listener
    function setupEventListeners() {
        // Xử lý paste nội dung
        jQuery("#qpContent").on("paste", function (e) {
            e.preventDefault();
            jQuery(this).val("");
            showLoading();

            const pastedText = e.originalEvent.clipboardData.getData('text');
            jQuery(this).val(pastedText);

            setTimeout(function() {
                const chapters = performAction();
                hideLoading();
                showNotification(`Đã nhập ${chapters} chương`, 'success');
            }, 100);
        });

        jQuery('#qpButtonRemoveEmpty').on('click', removeEmptyChapters);
        jQuery('#qpButtonSubmit').on('click', submitChapters);
    }

    // Xử lý paste và tách chương
    function performAction() {
        try {
            console.log("Starting performAction");
            var text = jQuery("#qpContent").val();

            if (!text) {
                showNotification('Không có nội dung để tách chương', 'error');
                return 0;
            }

            var debugOutput = [];
            var chapters = [];
            var lines = text.split('\n');
            var currentChapter = [];
            var lastTitle = null;

            debugOutput.push("=== Processing Text ===");
            debugOutput.push(`Total lines: ${lines.length}`);
            debugOutput.push("=== Line Analysis ===");

            // Helper function to show exact whitespace
            function visualizeWhitespace(str) {
                return str.split('').map(c => {
                    if (c === '\t') return '\\t';
                    if (c === ' ') return '·';
                    if (c === '\n') return '\\n';
                    return c;
                }).join('');
            }

            for (let i = 0; i < lines.length; i++) {
                let line = lines[i];
                let isChapterTitle = /^\t[Cc]hương\s*\d+\s*:/.test(line) || /^\s{4,}[Cc]hương\s*\d+\s*:/.test(line);

                // Debug log with exact whitespace
                debugOutput.push(`Line ${i}: ${visualizeWhitespace(line.substring(0, 50))}${line.length > 50 ? '...' : ''}`);
                debugOutput.push(`  Is chapter: ${isChapterTitle}`);

                if (isChapterTitle) {
                    if (currentChapter.length > 0) {
                        if (line !== lastTitle) {
                            chapters.push(currentChapter.join('\n'));
                            currentChapter = [line];
                            lastTitle = line;
                            debugOutput.push(`  -> New chapter started`);
                        } else {
                            debugOutput.push(`  -> Skipped duplicate title`);
                        }
                    } else {
                        currentChapter = [line];
                        lastTitle = line;
                        debugOutput.push(`  -> First chapter started`);
                    }
                } else if (currentChapter.length > 0) {
                    currentChapter.push(line);
                }
            }

            if (currentChapter.length > 0) {
                chapters.push(currentChapter.join('\n'));
                debugOutput.push("-> Added final chapter");
            }

            debugOutput.push("=== Results ===");
            debugOutput.push(`Found ${chapters.length} chapters`);

            // Phân tách chương dài
            const processedChapters = [];
            for (let i = 0; i < chapters.length; i++) {
                const chapterLines = chapters[i].split('\n');
                const title = chapterLines.shift().trim();
                const chapterText = chapterLines.join('\n');

                // Đếm số ký tự của chương
                const charCount = chapterText.length;
                debugOutput.push(`Chapter ${i+1} character count: ${charCount}`);

                // Nếu chương có kích thước lớn hơn 20000 ký tự, chia nhỏ
                if (charCount > 20000) {
                    // Số chương cần tách
                    const parts = Math.ceil(charCount / 20000);
                    debugOutput.push(`Splitting into ${parts} parts`);

                    // Tính số ký tự cho mỗi phần
                    const charsPerPart = Math.ceil(charCount / parts);
                    debugOutput.push(`Characters per part: ~${charsPerPart}`);

                    // Chia chương thành các phần đều nhau dựa trên số ký tự
                    let currentText = chapterText;
                    let totalProcessed = 0;

                    for (let part = 0; part < parts; part++) {
                        // Xác định kích thước phần này
                        const isLastPart = part === parts - 1;
                        const targetSize = isLastPart ? currentText.length : charsPerPart;

                        // Tìm điểm kết thúc phù hợp (kết thúc câu hoặc đoạn văn)
                        let endPos = Math.min(targetSize, currentText.length);

                        // Tìm điểm kết thúc là cuối đoạn văn hoặc cuối câu gần với vị trí mục tiêu
                        if (!isLastPart && endPos < currentText.length) {
                            // Tìm vị trí xuống dòng gần nhất
                            const nextParagraph = currentText.indexOf('\n\n', endPos - 500);
                            if (nextParagraph !== -1 && nextParagraph < endPos + 500) {
                                endPos = nextParagraph + 2; // +2 để bao gồm cả ký tự xuống dòng
                            } else {
                                // Nếu không tìm thấy đoạn văn, tìm dấu kết thúc câu
                                const sentenceEnd = Math.max(
                                    currentText.lastIndexOf('. ', endPos),
                                    currentText.lastIndexOf('! ', endPos),
                                    currentText.lastIndexOf('? ', endPos)
                                );

                                if (sentenceEnd !== -1 && sentenceEnd > endPos - 500) {
                                    endPos = sentenceEnd + 2; // +2 để bao gồm dấu kết thúc câu và khoảng trắng
                                }
                            }
                        }

                        // Lấy nội dung của phần này
                        const partContent = currentText.substring(0, endPos);
                        totalProcessed += partContent.length;

                        // Cập nhật text còn lại cho phần tiếp theo
                        currentText = currentText.substring(endPos);

                        // Tạo tiêu đề phần: chỉ lấy tiêu đề gốc và thêm phần chia
                        let chapterTitle = title;
                        if (title.includes(':')) {
                            chapterTitle = title.substring(title.indexOf(':') + 1).trim();
                        }

                        // Thêm thông tin phần vào tiêu đề gốc
                        let newTitle = `${title} (Phần ${part+1}/${parts})`;
                        processedChapters.push(newTitle + '\n' + partContent);

                        debugOutput.push(`Part ${part+1}: ${partContent.length} chars`);
                    }

                    debugOutput.push(`Total processed: ${totalProcessed}/${charCount} chars`);
                } else {
                    // Giữ nguyên chương nếu không cần chia
                    processedChapters.push(chapters[i]);
                }
            }

            debugOutput.push(`After processing: ${processedChapters.length} chapters`);

            // Giới hạn chỉ lấy 10 chương đầu tiên vào form, phần còn lại sẽ copy vào clipboard
            const chaptersToFill = processedChapters.slice(0, MAX_CHAPTER_POST);
            const remainingChapters = processedChapters.slice(MAX_CHAPTER_POST);

            // Fill chapters into forms
            var titles = jQuery("input[name^='chap_name']");
            var contents = jQuery("textarea[name^='introduce']");
            var advs = jQuery("textarea[name^='adv']");

            debugOutput.push(`Forms found: ${titles.length}`);

            if (processedChapters.length === 0) {
                showNotification('Không tìm thấy chương nào', 'error');
                jQuery('#debug-output').text(debugOutput.join('\n'));
                return;
            }

            // Nếu có chương còn lại, sao chép vào clipboard
            if (remainingChapters.length > 0) {
                debugOutput.push(`${remainingChapters.length} chapters will be copied to clipboard`);
            }

            // Tạo thêm form nếu số chương cần điền nhiều hơn số form hiện có
            const neededForms = chaptersToFill.length - titles.length;
            if (neededForms > 0 && titles.length < MAX_CHAPTER_POST) {
                debugOutput.push(`Need to add ${neededForms} more forms`);
                for (let i = 0; i < neededForms && (titles.length + i) < MAX_CHAPTER_POST; i++) {
                    addNewChapter();
                }
                // Cập nhật lại danh sách các form sau khi thêm
                titles = jQuery("input[name^='chap_name']");
                contents = jQuery("textarea[name^='introduce']");
                advs = jQuery("textarea[name^='adv']");
            }

            debugOutput.push(`Filling ${chaptersToFill.length} chapters into forms`);

            // Điền nội dung vào form
            jQuery.each(titles, function(k, v) {
                if (k < chaptersToFill.length) {
                    var content = chaptersToFill[k].split('\n');
                    var title = content.shift().trim();
                    //Preserve the "Chương X:" prefix
                    var originalTitle = title;


                    debugOutput.push(`\nFilling chapter ${k + 1}:`);
                    debugOutput.push(`Original title: ${title}`);
                    debugOutput.push(`Extracted title: ${originalTitle}`);
                    debugOutput.push(`Content length: ${content.length} lines`);

                    titles[k].value = originalTitle;
                    contents[k].value = headerSign + "\r\n" + content.join('\n') + "\r\n" + footerSign;
                    if (advs[k]) advs[k].value = "";

                    // Trigger character counter update
                    jQuery(contents[k]).trigger('input');
                }
            });

            // Sao chép các chương còn lại vào clipboard nếu có
            if (remainingChapters.length > 0) {
                try {
                    // Tạo nội dung clipboard với định dạng rõ ràng để dễ phân biệt các chương
                    const clipboardContent = remainingChapters.map(chap => chap.trim()).join('\n\n---CHAPTER_SEPARATOR---\n\n');

                    // Thử trước với Clipboard API (hiện đại)
                    if (navigator.clipboard && navigator.clipboard.writeText) {
                        navigator.clipboard.writeText(clipboardContent)
                            .then(() => {
                                debugOutput.push(`Đã sao chép ${remainingChapters.length} chương vào clipboard (Clipboard API)`);
                                showNotification(`Đã sao chép ${remainingChapters.length} chương vào clipboard`, 'success');
                            })
                            .catch(err => {
                                throw err; // Chuyển đến phương pháp dự phòng
                            });
                    } else {
                        // Phương pháp dự phòng với execCommand (cũ)
                        const tempTextarea = document.createElement('textarea');
                        tempTextarea.style.position = 'fixed';
                        tempTextarea.style.top = '0';
                        tempTextarea.style.left = '0';
                        tempTextarea.style.width = '2em';
                        tempTextarea.style.height = '2em';
                        tempTextarea.style.opacity = '0';
                        tempTextarea.style.pointerEvents = 'none';
                        tempTextarea.value = clipboardContent;

                        document.body.appendChild(tempTextarea);
                        tempTextarea.focus();
                        tempTextarea.select();

                        const successful = document.execCommand('copy');
                        document.body.removeChild(tempTextarea);

                        if (!successful) {
                            throw new Error('Không thể sao chép vào clipboard');
                        }

                        debugOutput.push(`Đã sao chép ${remainingChapters.length} chương vào clipboard (execCommand)`);
                        showNotification(`Đã sao chép ${remainingChapters.length} chương vào clipboard`, 'success');
                    }
                } catch (err) {
                    console.error('Lỗi khi sao chép vào clipboard:', err);
                    debugOutput.push(`Lỗi khi sao chép vào clipboard: ${err.message}`);
                    showNotification('Không thể sao chép vào clipboard. Vui lòng thử lại.', 'error');

                    // Hiển thị textarea để copy thủ công nếu tự động không thành công
                    const manualCopyArea = document.createElement('div');
                    manualCopyArea.style.position = 'fixed';
                    manualCopyArea.style.top = '50%';
                    manualCopyArea.style.left = '50%';
                    manualCopyArea.style.transform = 'translate(-50%, -50%)';
                    manualCopyArea.style.backgroundColor = 'white';
                    manualCopyArea.style.padding = '20px';
                    manualCopyArea.style.borderRadius = '8px';
                    manualCopyArea.style.boxShadow = '0 4px 6px -1px rgba(0, 0, 0, 0.1)';
                    manualCopyArea.style.zIndex = '10000';
                    manualCopyArea.style.maxWidth = '80%';
                    manualCopyArea.style.maxHeight = '80%';
                    manualCopyArea.style.overflow = 'auto';

                    manualCopyArea.innerHTML = `
                        <h3 style="margin-top: 0;">Sao chép thủ công</h3>
                        <p>Không thể sao chép tự động. Vui lòng chọn toàn bộ nội dung bên dưới và sao chép (Ctrl+C):</p>
                        <textarea style="width: 100%; height: 300px; padding: 10px;">${clipboardContent}</textarea>
                        <div style="text-align: right; margin-top: 10px;">
                            <button id="closeManualCopy" style="padding: 8px 16px; background: #3b82f6; color: white; border: none; border-radius: 4px; cursor: pointer;">Đóng</button>
                        </div>
                    `;

                    document.body.appendChild(manualCopyArea);

                    document.getElementById('closeManualCopy').addEventListener('click', () => {
                        document.body.removeChild(manualCopyArea);
                    });
                }
            }

            jQuery("#qpButtonSubmit").removeClass("btn-disable").addClass("btn-success");
            jQuery("#qpContent").val("Đã thực hiện xong");

            // Hiển thị thông báo sau khi xử lý xong
            if (remainingChapters.length > 0) {
                let message = `Đã sử lý ${chapters.length} chương\n`;
                message += `Đã nhập ${MAX_CHAPTER_POST} chương\n`;
                message += `Đã coppy ${remainingChapters.length} chương`;

                // Đếm số chương được chia
                let splitChapters = 0;
                for (let i = 0; i < chapters.length; i++) {
                    const chapterText = chapters[i].split('\n').slice(1).join('\n');
                    if (chapterText.length > 20000) {
                        splitChapters++;
                    }
                }

                if (processedChapters.length > chapters.length) {
                    message += `\nCó ${splitChapters} chương chia thành ${processedChapters.length - (chapters.length - splitChapters)} chương`;
                }

                showNotification(message, 'success');
            } else if (processedChapters.length > chapters.length) {
                // Đếm số chương được chia
                let splitChapters = 0;
                for (let i = 0; i < chapters.length; i++) {
                    const chapterText = chapters[i].split('\n').slice(1).join('\n');
                    if (chapterText.length > 20000) {
                        splitChapters++;
                    }
                }

                let message = `Đã sử lý ${chapters.length} chương\n`;
                message += `Đã nhập ${processedChapters.length} chương\n`;
                message += `Có ${splitChapters} chương chia thành ${processedChapters.length - (chapters.length - splitChapters)} chương`;
                showNotification(message, 'success');
            } else {
                showNotification(`Đã sử lý ${chapters.length} chương\nĐã nhập ${processedChapters.length} chương vào form`, 'success');
            }

            // Show debug output
            jQuery('#debug-output').text(debugOutput.join('\n'));

            return processedChapters.length;
        } catch (e) {
            console.error("Error in performAction:", e);
            showNotification('Có lỗi khi tách chương', 'error');
            return 0;
        }
    }

    // Xóa chương trống
    function removeEmptyChapters() {
        const forms = document.querySelectorAll('[data-gen="MK_GEN"]');
        let removed = 0;

        forms.forEach(form => {
            const content = form.querySelector('textarea[name^="introduce"]').value.trim();
            if (!content) {
                form.remove();
                removed++;
                updateChapNumber(false);
            }
        });

        showNotification(`Đã xử lý ${forms.length} chương`, 'info');
    }

    // Đăng chương
    function submitChapters() {
        const forms = document.querySelectorAll('[data-gen="MK_GEN"]');
        let hasError = false;

        forms.forEach(form => {
            const contentTextarea = form.querySelector('textarea[name^="introduce"]');
            const content = contentTextarea.value;
            if (content.length < 3000) {
                // Đánh dấu form với màu đỏ rõ ràng hơn
                contentTextarea.style.border = '3px solid #ff0000';
                contentTextarea.style.backgroundColor = 'rgba(255, 0, 0, 0.08)';
                // Đổi màu chữ để dễ đọc hơn trên nền đỏ
                contentTextarea.style.color = '#cc0000';
                // Thêm đường viền ngoài cho parent để làm nổi bật toàn bộ form
                contentTextarea.parentNode.style.border = '1px solid #ff0000';
                contentTextarea.parentNode.style.padding = '5px';
                contentTextarea.parentNode.style.borderRadius = '5px';
                contentTextarea.parentNode.style.backgroundColor = 'rgba(255, 0, 0, 0.03)';
                hasError = true;

                // Thêm thông báo lỗi bên dưới textarea nổi bật hơn
                let errorMsg = form.querySelector('.chapter-length-error');
                if (!errorMsg) {
                    errorMsg = document.createElement('div');
                    errorMsg.className = 'chapter-length-error';
                    errorMsg.style.color = '#ff0000';
                    errorMsg.style.marginTop = '5px';
                    errorMsg.style.fontSize = '14px';
                    errorMsg.style.fontWeight = 'bold';
                    errorMsg.style.padding = '5px 10px';
                    errorMsg.style.backgroundColor = '#fff0f0';
                    errorMsg.style.border = '1px solid #ff0000';
                    errorMsg.style.borderRadius = '3px';
                    contentTextarea.parentNode.appendChild(errorMsg);
                }
                errorMsg.textContent = `⚠️ Chương quá ngắn: ${content.length}/3000 ký tự cần thiết`;
            } else {
                // Reset tất cả các style khi chương đủ dài
                contentTextarea.style.border = '';
                contentTextarea.style.backgroundColor = '';
                contentTextarea.style.color = '';
                contentTextarea.parentNode.style.border = '';
                contentTextarea.parentNode.style.padding = '';
                contentTextarea.parentNode.style.borderRadius = '';
                contentTextarea.parentNode.style.backgroundColor = '';

                // Xóa thông báo lỗi nếu có
                const errorMsg = form.querySelector('.chapter-length-error');
                if (errorMsg) {
                    errorMsg.remove();
                }
            }
        });

        if (hasError) {
            showNotification('Có chương ngắn hơn 3000 ký tự, vui lòng kiểm tra các ô màu đỏ', 'error');
            return;
        }

        showLoading();
        // Submit form gốc
        document.querySelector('form[name="postChapForm"] button[type="submit"]').click();
        setTimeout(hideLoading, 2000);
    }

    // Hiển thị thông báo
    function showNotification(message, type = 'info') {
        const notificationArea = document.getElementById('notification-area');
        // Chuyển đổi xuống dòng thành thẻ <br> để hiển thị đúng trong HTML
        notificationArea.innerHTML = message.replace(/\n/g, '<br>');
        notificationArea.className = `mt-3 text-center notification-${type}`;
        // Thêm padding để thông báo đẹp hơn khi hiển thị nhiều dòng
        notificationArea.style.padding = '10px';
    }

    // Hiển thị loading
    function showLoading() {
        const loading = document.createElement('div');
        loading.className = 'loading-overlay';
        loading.innerHTML = `
            <div class="loading-spinner"></div>
        `;
        document.body.appendChild(loading);
    }

    function hideLoading() {
        const loading = document.querySelector('.loading-overlay');
        if (loading) {
            loading.remove();
        }
    }

    //Setup character counter
    function setupCharacterCounter() {
        jQuery('.chapter-content').on('input', function() {
            const textarea = jQuery(this);
            const currentCount = textarea.val().length;
            textarea.next('.character-counter').find('.current-count').text(currentCount);

            // Hiển thị số ký tự
            const counterElement = textarea.next('.character-counter');

            // Cảnh báo nếu chương quá dài
            if (currentCount > 20000) {
                counterElement.css('color', '#ff6600');
                if (counterElement.find('.char-warning').length === 0) {
                    counterElement.append(`<div class="char-warning" style="color: #ff6600; font-weight: bold;">Chương này dài (>2000 ký tự), sẽ được tự động chia khi đăng</div>`);
                }
            } else {
                counterElement.css('color', '#666');
                counterElement.find('.word-warning').remove();
            }
        });

        // Trigger input event để cập nhật counters cho các textarea đã có nội dung
        jQuery('.chapter-content').trigger('input');
    }

    // Khởi tạo script
    function init() {
        createInterface();
        initializeChapters();
        setupCharacterCounter(); // Initialize character counters on page load
    }

    init();
})();