ID Other
1 First
2 Second
50 Another

Click the code to copy it

function enableTableIdsCopy(options = {}) {
    // Default options
    const config = {
        tableSelector: 'table',
        idColumnSelector: 'th',
        caseSensitive: false,
        buttonText: 'Copy Table IDs',
        copiedTextDuration: 1000,
        ...options
    };

    /**
     * Copies ID values from a table to the clipboard as a CSV
     * @param {HTMLTableElement} table - The table to copy IDs from
     * @param {HTMLButtonElement} button - The button that was clicked
     * @returns {boolean} Whether IDs were successfully copied
     */
    function copyTableIdsToClipboard(table, button) {
        // Find the ID column header
        const headers = table.querySelectorAll(config.idColumnSelector);
        let idColumnIndex = -1;

        // Search for ID column (case-insensitive by default)
        headers.forEach((header, index) => {
            const headerText = config.caseSensitive 
                ? header.textContent.trim() 
                : header.textContent.trim().toLowerCase();
            
            const isIdColumn = config.caseSensitive
                ? headerText === 'id'
                : headerText === 'id';

            if (isIdColumn) {
                idColumnIndex = index;
            }
        });

        // Validate ID column found
        if (idColumnIndex === -1) {
            console.error('No ID column found in table', table);
            return false;
        }

        // Extract ID values
        const rows = table.querySelectorAll('tr');
        const idValues = [];

        // Skip header row, start from index 1
        for (let i = 1; i < rows.length; i++) {
            const cells = rows[i].querySelectorAll('td');
            if (cells.length > idColumnIndex) {
                const idValue = cells[idColumnIndex].textContent.trim();
                if (idValue) {
                    idValues.push(idValue);
                }
            }
        }

        // Copy to clipboard
        if (idValues.length > 0) {
            const csvString = idValues.join(',');
            
            // Temporarily disable button and change text
            const originalText = button.textContent;
            button.style.transition = 'opacity 0.3s ease-in-out';
            
            // Use modern clipboard API
            navigator.clipboard.writeText(csvString)
                .then(() => {
                    console.log(`Copied ${idValues.length} ID(s) to clipboard`);
                    
                    // Change button text with fade effect
                    button.style.opacity = 0;
                    setTimeout(() => {
                        button.textContent = 'Copied!';
                        button.style.opacity = 1;
                    }, 300);

                    // Revert button text after specified duration
                    setTimeout(() => {
                        button.style.opacity = 0;
                        setTimeout(() => {
                            button.textContent = originalText;
                            button.style.opacity = 1;
                        }, 300);
                    }, config.copiedTextDuration);

                    // Optional: Add visual feedback
                    flashClipboardFeedback();
                })
                .catch(err => {
                    console.error('Failed to copy IDs to clipboard', err);
                });

            return true;
        } else {
            console.warn('No ID values found in table', table);
            return false;
        }
    }

    /**
     * Provides visual feedback when IDs are copied
     */
    function flashClipboardFeedback() {
        const feedback = document.createElement('div');
        feedback.textContent = 'IDs Copied!';
        feedback.style.position = 'fixed';
        feedback.style.top = '20px';
        feedback.style.right = '20px';
        feedback.style.backgroundColor = 'green';
        feedback.style.color = 'white';
        feedback.style.padding = '10px';
        feedback.style.borderRadius = '5px';
        feedback.style.zIndex = '1000';
        
        document.body.appendChild(feedback);
        
        setTimeout(() => {
            document.body.removeChild(feedback);
        }, 2000);
    }

    // Find all tables matching the selector
    const tables = document.querySelectorAll(config.tableSelector);

    // Process each table
    tables.forEach((table, index) => {
        // Create copy button
        const copyButton = document.createElement('button');
        copyButton.textContent = `${config.buttonText}${tables.length > 1 ? ` (Table ${index + 1})` : ''}`;
        
        // Style the button
        copyButton.style.margin = '10px 0';
        copyButton.style.padding = '10px 15px';
        copyButton.style.backgroundColor = '#4CAF50';
        copyButton.style.color = 'white';
        copyButton.style.border = 'none';
        copyButton.style.borderRadius = '5px';
        copyButton.style.cursor = 'pointer';
        copyButton.style.transition = 'background-color 0.3s, opacity 0.3s ease-in-out';
        copyButton.style.display = 'block';

        // Add hover effects
        copyButton.addEventListener('mouseenter', () => {
            copyButton.style.backgroundColor = '#45a049';
        });
        copyButton.addEventListener('mouseleave', () => {
            copyButton.style.backgroundColor = '#4CAF50';
        });

        // Add click event to copy IDs
        copyButton.addEventListener('click', () => copyTableIdsToClipboard(table, copyButton));

        // Insert the button directly before the table
        table.parentNode.insertBefore(copyButton, table);
    });

    // Return the number of tables processed
    return tables.length;
}

// Automatically run the function when the script loads
enableTableIdsCopy();