BBCode Table Generator for Bitcointalk & Altcoinstalks (with Full Formatting)

Genera tabelle in BBCode con formattazione avanzata (colore testo, grandezza font, tipo font, glow)

06.09.2025 itibariyledir. En son verisyonu görün.

// ==UserScript==
// @name         BBCode Table Generator for Bitcointalk & Altcoinstalks (with Full Formatting)
// @namespace    http://tampermonkey.net/
// @version      2.9
// @description  Genera tabelle in BBCode con formattazione avanzata (colore testo, grandezza font, tipo font, glow)
// @author       Ace D.Portugal
// @match        *://bitcointalk.org/*
// @match        *://altcoinstalks.com/*
// @match        *://www.altcoinstalks.com/*
// @grant        GM_setClipboard
// @grant        GM_notification
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        unsafeWindow
// ==/UserScript==

(function() {
    'use strict';

    function isVisible(el) {
        return el && el.offsetParent !== null && window.getComputedStyle(el).display !== 'none';
    }

    function waitForElement(selectors, callback, maxAttempts = 40, interval = 500) {
        let attempts = 0;
        const checkInterval = setInterval(() => {
            for (const selector of selectors) {
                const element = document.querySelector(selector);
                if (element && isVisible(element)) {
                    clearInterval(checkInterval);
                    callback(element);
                    return;
                }
            }
            if (attempts++ >= maxAttempts) {
                clearInterval(checkInterval);
                console.error("Nessun elemento visibile trovato con i selettori:", selectors);
            }
        }, interval);
    }

    function loadTemplates() {
        return GM_getValue('bbcodeTableTemplates', []);
    }

    function saveTemplates(templates) {
        GM_setValue('bbcodeTableTemplates', templates);
    }

    function addTemplate(name, data) {
        const templates = loadTemplates();
        templates.push({ name, data });
        saveTemplates(templates);
    }

    function removeTemplate(index) {
        const templates = loadTemplates();
        templates.splice(index, 1);
        saveTemplates(templates);
    }

    function insertBBCode(openTag, closeTag = '') {
        const textarea = document.getElementById('bbcodeDataInput');
        if (!textarea) return;
        const start = textarea.selectionStart;
        const end = textarea.selectionEnd;
        const selectedText = textarea.value.substring(start, end);
        const newText = textarea.value.substring(0, start) + openTag + selectedText + closeTag + textarea.value.substring(end);
        textarea.value = newText;
        textarea.focus();
        textarea.selectionStart = start + openTag.length;
        textarea.selectionEnd = end + openTag.length;
    }

    function bbcodeToHtml(bbcode) {
        return bbcode
            .replace(/\[b\](.*?)\[\/b\]/g, '<strong>$1</strong>')
            .replace(/\[i\](.*?)\[\/i\]/g, '<em>$1</em>')
            .replace(/\[u\](.*?)\[\/u\]/g, '<u>$1</u>')
            .replace(/\[url=(.*?)\](.*?)\[\/url\]/g, '<a href="$1" target="_blank">$2</a>')
            .replace(/\[img\](.*?)\[\/img\]/g, '<img src="$1" style="max-width: 100%; height: auto;" />')
            .replace(/\[color=(.*?)\](.*?)\[\/color\]/g, '<span style="color: $1;">$2</span>')
            .replace(/\[size=(.*?)\](.*?)\[\/size\]/g, '<span style="font-size: $1;">$2</span>')
            .replace(/\[font=(.*?)\](.*?)\[\/font\]/g, '<span style="font-family: $1;">$2</span>')
            .replace(/\[glow=(.*?),2,300\](.*?)\[\/glow\]/g, '<span style="text-shadow: 0 0 8px $1;">$2</span>');
    }

    window.addEventListener('load', function() {
        setTimeout(function() {
            const replySelectors = [
                'textarea[name="message"]',
                '.postingbox',
                '#quick_reply',
                'form#postmodify textarea[name="message"]',
                '#vB_Editor_QR_textarea',
                '#fast_reply',
                '#message',
                'textarea.editor',
            ];

            waitForElement(replySelectors, function(replyBox) {
                const button = document.createElement('button');
                button.textContent = 'Genera Tabella da Testo';
                button.style.margin = '10px';
                button.style.padding = '5px 10px';
                button.style.backgroundColor = '#4CAF50';
                button.style.color = 'white';
                button.style.border = 'none';
                button.style.borderRadius = '4px';
                button.style.cursor = 'pointer';
                button.onclick = openTableGenerator;
                replyBox.parentNode.insertBefore(button, replyBox);
                console.log("Pulsante aggiunto con successo!");
            });
        }, 2000);
    });

    function openTableGenerator(e) {
        e.preventDefault();
        e.stopPropagation();

        const oldOverlay = document.getElementById('bbcodeTableOverlay');
        if (oldOverlay) oldOverlay.remove();
        const oldModal = document.getElementById('bbcodeTableModal');
        if (oldModal) oldModal.remove();

        const overlay = document.createElement('div');
        overlay.id = 'bbcodeTableOverlay';
        overlay.style.position = 'fixed';
        overlay.style.top = '0';
        overlay.style.left = '0';
        overlay.style.width = '100%';
        overlay.style.height = '100%';
        overlay.style.backgroundColor = 'rgba(0,0,0,0.7)';
        overlay.style.zIndex = '9998';
        overlay.style.display = 'flex';
        overlay.style.justifyContent = 'center';
        overlay.style.alignItems = 'center';

        const modal = document.createElement('div');
        modal.id = 'bbcodeTableModal';
        modal.style.background = 'white';
        modal.style.padding = '20px';
        modal.style.borderRadius = '5px';
        modal.style.maxWidth = '80%';
        modal.style.maxHeight = '80%';
        modal.style.overflow = 'auto';
        modal.style.zIndex = '9999';

        const templates = loadTemplates();
        let templateOptions = '<option value="">-- Seleziona un modello --</option>';
        templates.forEach((template, index) => {
            templateOptions += `<option value="${index}">${template.name}</option>`;
        });

        modal.innerHTML = `
            <h3 style="margin-top: 0;">Genera Tabella da Testo</h3>

            <div style="margin-bottom: 10px;">
                <label>Modelli salvati: </label>
                <select id="bbcodeTemplateSelect" style="padding: 5px;">
                    ${templateOptions}
                </select>
                <button id="bbcodeLoadTemplate" style="margin-left: 5px; padding: 5px 10px; background-color: #2196F3; color: white; border: none; border-radius: 4px;">Carica</button>
                <button id="bbcodeDeleteTemplate" style="margin-left: 5px; padding: 5px 10px; background-color: #f44336; color: white; border: none; border-radius: 4px;">Elimina</button>
            </div>

            <div style="margin-bottom: 10px;">
                <label>Nome modello: </label>
                <input type="text" id="bbcodeTemplateName" style="padding: 5px; width: 200px;" placeholder="Nome del modello">
                <button id="bbcodeSaveTemplate" style="margin-left: 5px; padding: 5px 10px; background-color: #4CAF50; color: white; border: none; border-radius: 4px;">Salva Modello</button>
            </div>

            <p>Inserisci i dati separando le colonne con una virgola (,) e le righe con un a capo.</p>

            <div style="margin-bottom: 10px;">
                <div style="margin-bottom: 5px; font-weight: bold;">Pulsanti di formattazione rapida:</div>
                <button class="format-button" data-open="[b]" data-close="[/b]" style="margin-right: 5px; padding: 3px 8px; background-color: #4CAF50; color: white; border: none; border-radius: 3px;">Grassetto</button>
                <button class="format-button" data-open="[i]" data-close="[/i]" style="margin-right: 5px; padding: 3px 8px; background-color: #2196F3; color: white; border: none; border-radius: 3px;">Corsivo</button>
                <button class="format-button" data-open="[u]" data-close="[/u]" style="margin-right: 5px; padding: 3px 8px; background-color: #9C27B0; color: white; border: none; border-radius: 3px;">Sottolineato</button>
                <button class="format-button" data-open="[url=" data-close="][/url]" style="margin-right: 5px; padding: 3px 8px; background-color: #FF5722; color: white; border: none; border-radius: 3px;">Link</button>
                <button class="format-button" data-open="[img]" data-close="[/img]" style="margin-right: 5px; padding: 3px 8px; background-color: #FF9800; color: white; border: none; border-radius: 3px;">Immagine</button>
                <button class="format-button" data-open="[color=" data-close="][/color]" style="margin-right: 5px; padding: 3px 8px; background-color: #795548; color: white; border: none; border-radius: 3px;">Colore Testo</button>
                <button class="format-button" data-open="[size=" data-close="][/size]" style="margin-right: 5px; padding: 3px 8px; background-color: #607D8B; color: white; border: none; border-radius: 3px;">Dimensione Font</button>
                <button class="format-button" data-open="[font=" data-close="][/font]" style="margin-right: 5px; padding: 3px 8px; background-color: #558B2F; color: white; border: none; border-radius: 3px;">Tipo Font</button>
            </div>

            <div style="margin-bottom: 10px;">
                <div style="margin-bottom: 5px; font-weight: bold;">Opzioni di formattazione globale:</div>
                <label><input type="checkbox" id="bbcodeBoldHeaders" checked> Header in grassetto</label>
                <label style="margin-left: 10px;"><input type="checkbox" id="bbcodeGlowHeaders"> Effetto Glow</label>
                <label style="margin-left: 10px;">Colore glow: <input type="color" id="bbcodeGlowColor" value="#ff0000"></label>
            </div>

            <textarea id="bbcodeDataInput" style="width: 100%; height: 100px; margin: 10px 0; padding: 8px; box-sizing: border-box;" placeholder="Esempio:
Match, Date, Odds
Inter vs Juventus, 13/08/24, X
Milan vs Roma, 14/08/24, 2"></textarea>

            <button id="bbcodeGenerateTable" style="margin: 5px; padding: 5px 10px; background-color: #4CAF50; color: white; border: none; border-radius: 4px;">Genera Tabella</button>

            <div id="bbcodeTablePreview" style="margin: 10px 0; border: 1px solid #ddd; padding: 10px; min-height: 50px;"></div>

            <div>
                <button id="bbcodeCopyBBCode" style="margin: 5px; padding: 5px 10px; background-color: #2196F3; color: white; border: none; border-radius: 4px;">Copia BBCode</button>
                <button id="bbcodeCloseModal" style="margin: 5px; padding: 5px 10px; background-color: #f44336; color: white; border: none; border-radius: 4px;">Chiudi</button>
            </div>
        `;

        overlay.appendChild(modal);
        document.body.appendChild(overlay);

        // Aggiungi gestione pulsanti di formattazione
        const formatButtons = modal.querySelectorAll('.format-button');
        formatButtons.forEach(button => {
            button.addEventListener('click', function() {
                const openTag = this.getAttribute('data-open');
                const closeTag = this.getAttribute('data-close') || '';
                if (openTag === '[url=') {
                    const url = prompt("Inserisci l'URL:", "https://");
                    if (url) insertBBCode(`[url=${url}]`, '[/url]');
                } else if (openTag === '[img]') {
                    const imgUrl = prompt("Inserisci l'URL dell'immagine:", "https://");
                    if (imgUrl) insertBBCode(`[img]${imgUrl}[/img]`, '');
                } else if (openTag === '[color=') {
                    const color = prompt("Inserisci il colore (es: red, #ff0000):", "#ff0000");
                    if (color) insertBBCode(`[color=${color}]`, '[/color]');
                } else if (openTag === '[size=') {
                    const size = prompt("Inserisci la dimensione del font (es: 12pt, 1em):", "12pt");
                    if (size) insertBBCode(`[size=${size}]`, '[/size]');
                } else if (openTag === '[font=') {
                    const font = prompt("Inserisci il tipo di font (es: Arial, Verdana):", "Arial");
                    if (font) insertBBCode(`[font=${font}]`, '[/font]');
                } else {
                    insertBBCode(openTag, closeTag);
                }
            });
        });

        // Carica un modello
        modal.querySelector('#bbcodeLoadTemplate').addEventListener('click', function() {
            const select = modal.querySelector('#bbcodeTemplateSelect');
            const index = select.value;
            if (index !== "") {
                const templates = loadTemplates();
                modal.querySelector('#bbcodeDataInput').value = templates[index].data;
            }
        });

        // Elimina un modello
        modal.querySelector('#bbcodeDeleteTemplate').addEventListener('click', function() {
            const select = modal.querySelector('#bbcodeTemplateSelect');
            const index = select.value;
            if (index !== "") {
                removeTemplate(index);
                select.remove(select.selectedIndex);
                GM_notification({text: 'Modello eliminato!', title: 'Successo'});
            }
        });

        // Salva un modello
        modal.querySelector('#bbcodeSaveTemplate').addEventListener('click', function() {
            const name = modal.querySelector('#bbcodeTemplateName').value.trim();
            const data = modal.querySelector('#bbcodeDataInput').value.trim();
            if (name && data) {
                addTemplate(name, data);
                GM_notification({text: 'Modello salvato!', title: 'Successo'});
            } else {
                alert("Inserisci un nome e dei dati per il modello.");
            }
        });

        modal.querySelector('#bbcodeGenerateTable').addEventListener('click', generateTableFromText);
        modal.querySelector('#bbcodeCopyBBCode').addEventListener('click', copyBBCode);
        modal.querySelector('#bbcodeCloseModal').addEventListener('click', () => {
            overlay.remove();
            modal.remove();
        });
    }

    function generateTableFromText() {
        const inputText = document.getElementById('bbcodeDataInput').value.trim();
        const lines = inputText.split('\n');
        if (lines.length < 2) {
            alert("Inserisci almeno due righe di dati (intestazione + almeno una riga).");
            return;
        }

        const isBoldHeaders = document.getElementById('bbcodeBoldHeaders').checked;
        const isGlowHeaders = document.getElementById('bbcodeGlowHeaders').checked;
        const glowColorHex = document.getElementById('bbcodeGlowColor').value;

        let bbcode = '[table]';
        let tableHTML = '<table border="1" style="border-collapse: collapse; width: 100%; margin-top: 10px;">';

        for (let i = 0; i < lines.length; i++) {
            const line = lines[i].trim();
            if (line === '') continue;
            const cells = line.split(',').map(cell => cell.trim());
            if (cells.length === 0) continue;

            tableHTML += '<tr>';
            bbcode += '[tr]';

            for (let j = 0; j < cells.length; j++) {
                const cell = cells[j];
                const isHeader = (i === 0);
                let bbcodeCell = cell;
                let htmlCell = bbcodeToHtml(cell);

                if (isHeader) {
                    if (isBoldHeaders) bbcodeCell = `[b]${bbcodeCell}[/b]`;
                    if (isGlowHeaders) bbcodeCell = `[glow=${glowColorHex},2,300]${bbcodeCell}[/glow]`;
                    if (isBoldHeaders) htmlCell = `<strong>${htmlCell}</strong>`;
                    if (isGlowHeaders) htmlCell = `<span style="text-shadow: 0 0 8px ${glowColorHex};">${htmlCell}</span>`;
                }

                tableHTML += `<td style="border: 1px solid #ddd; padding: 5px;">${htmlCell}</td>`;
                bbcode += `[td]${bbcodeCell}[/td]`;
            }

            tableHTML += '</tr>';
            bbcode += '[/tr]';
        }

        tableHTML += '</table>';
        bbcode += '[/table]';

        const preview = document.getElementById('bbcodeTablePreview');
        preview.innerHTML = tableHTML;
        preview.setAttribute('data-bbcode', bbcode);
    }

    function copyBBCode() {
        const preview = document.getElementById('bbcodeTablePreview');
        const bbcode = preview.getAttribute('data-bbcode');
        if (bbcode) {
            GM_setClipboard(bbcode, 'text');
            GM_notification({text: 'BBCode copiato negli appunti!', title: 'Successo'});
        } else {
            alert("Genera prima la tabella!");
        }
    }

    function hexToColorName(hex) {
        // Ora supportiamo anche i colori esadecimali direttamente
        return hex;
    }
})();
长期地址
遇到问题?请前往 GitHub 提 Issues。