BBCode Table Generator for Bitcointalk & Altcoinstalks (with Templates & Quick Formatting)

Genera tabelle in BBCode con salvataggio modelli e pulsanti di formattazione rapida

Versión del día 6/9/2025. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         BBCode Table Generator for Bitcointalk & Altcoinstalks (with Templates & Quick Formatting)
// @namespace    http://tampermonkey.net/
// @version      2.5
// @description  Genera tabelle in BBCode con salvataggio modelli e pulsanti di formattazione rapida
// @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';

    // Funzione per verificare se un elemento è visibile
    function isVisible(el) {
        return el && el.offsetParent !== null && window.getComputedStyle(el).display !== 'none';
    }

    // Funzione per attendere che un elemento sia pronto
    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);
    }

    // Carica i modelli salvati
    function loadTemplates() {
        return GM_getValue('bbcodeTableTemplates', []);
    }

    // Salva i modelli
    function saveTemplates(templates) {
        GM_setValue('bbcodeTableTemplates', templates);
    }

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

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

    window.addEventListener('load', function() {
        setTimeout(function() {
            const replySelectors = [
                // Bitcointalk
                'textarea[name="message"]',
                '.postingbox',
                '#quick_reply',
                // Altcoinstalks
                '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 onclick="insertBBCode('[b]', '[/b]')" style="margin-right: 5px; padding: 3px 8px; background-color: #4CAF50; color: white; border: none; border-radius: 3px;">Grassetto</button>
                <button onclick="insertBBCode('[i]', '[/i]')" style="margin-right: 5px; padding: 3px 8px; background-color: #2196F3; color: white; border: none; border-radius: 3px;">Corsivo</button>
                <button onclick="insertBBCode('[url=', '[/url]')" style="margin-right: 5px; padding: 3px 8px; background-color: #9C27B0; color: white; border: none; border-radius: 3px;">Link</button>
                <button onclick="insertBBCode('[img]', '[/img]')" style="margin-right: 5px; padding: 3px 8px; background-color: #FF9800; color: white; border: none; border-radius: 3px;">Immagine</button>
            </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>

            <div style="margin: 10px 0;">
                <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>

            <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);

        // Funzione per inserire BBCode nel textarea
        window.insertBBCode = function(openTag, closeTag = '') {
            const textarea = document.getElementById('bbcodeDataInput');
            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;
        };

        // Carica un modello
        document.getElementById('bbcodeLoadTemplate').onclick = function() {
            const select = document.getElementById('bbcodeTemplateSelect');
            const index = select.value;
            if (index !== "") {
                const templates = loadTemplates();
                document.getElementById('bbcodeDataInput').value = templates[index].data;
            }
        };

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

        // Salva un modello
        document.getElementById('bbcodeSaveTemplate').onclick = function() {
            const name = document.getElementById('bbcodeTemplateName').value.trim();
            const data = document.getElementById('bbcodeDataInput').value.trim();
            if (name && data) {
                addTemplate(name, data);
                GM_notification({text: 'Modello salvato!', title: 'Successo'});
                // Aggiorna la lista dei modelli
                location.reload();
            } else {
                alert("Inserisci un nome e dei dati per il modello.");
            }
        };

        document.getElementById('bbcodeGenerateTable').onclick = generateTableFromText;
        document.getElementById('bbcodeCopyBBCode').onclick = copyBBCode;
        document.getElementById('bbcodeCloseModal').onclick = () => {
            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;
        const glowColorName = hexToColorName(glowColorHex) || glowColorHex.replace('#', '');

        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 = cell;

                if (isHeader) {
                    if (isBoldHeaders) bbcodeCell = `[b]${bbcodeCell}[/b]`;
                    if (isGlowHeaders) bbcodeCell = `[glow=${glowColorName},2,300]${bbcodeCell}[/glow]`;
                    htmlCell = isBoldHeaders ? `<b>${htmlCell}</b>` : htmlCell;
                    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) {
        const colorMap = {
            '#ff0000': 'red',
            '#00ff00': 'green',
            '#0000ff': 'blue',
            '#ffff00': 'yellow',
            '#ff00ff': 'magenta',
            '#00ffff': 'cyan',
            '#ffffff': 'white',
            '#000000': 'black',
            '#ffa500': 'orange',
            '#800080': 'purple'
        };
        return colorMap[hex.toLowerCase()] || null;
    }
})();