Jump to content

MediaWiki:Gadget-copyTable.js: Difference between revisions

From Insurer Brain
Content deleted Content added
No edit summary
No edit summary
 
Line 34: Line 34:
}
}


mw.hook( 'wikipage.content' ).add( function ( $content ) {
mw.hook( 'wikipage.content' ).add( function ( $content ) {
$content.find( 'table.wikitable' ).not( '.copy-table-added' ).each( function () {
$content.find( 'table.wikitable' ).not( '.copy-table-added' ).each( function () {
var $table = $( this ).addClass( 'copy-table-added' );
var $table = $( this ).addClass( 'copy-table-added' );


var $btn = $( '<button>' )
var $btn = $( '<button>' )
.addClass( 'copy-table-btn' )
.addClass( 'copy-table-btn' )
.attr( 'title', 'Copy table' )
.attr( 'title', 'Copy table' )
.html( COPY_ICON )
.html( COPY_ICON )
.on( 'click', function () {
.on( 'click', function () {
var tsv = tableToTSV( $table[ 0 ] );
var tsv = tableToTSV( $table[ 0 ] );
navigator.clipboard.writeText( tsv ).then( function () {
navigator.clipboard.writeText( tsv ).then( function () {
$btn.html( CHECK_ICON ).addClass( 'copy-table-btn--ok' );
$btn.html( CHECK_ICON ).addClass( 'copy-table-btn--ok' );
setTimeout( function () {
setTimeout( function () {
$btn.html( COPY_ICON ).removeClass( 'copy-table-btn--ok' );
$btn.html( COPY_ICON ).removeClass( 'copy-table-btn--ok' );
}, 2000 );
}, 2000 );
} );
} );
} );
} );


// Wrap table so button can be absolutely positioned
// If the table sits in a horizontal-scroll box (the house style wraps it
$table.wrap( '<div class="copy-table-wrapper">' );
// in <div style="overflow-x:auto">), wrap THAT box so the button lives
// OUTSIDE the scrolling area and stays pinned. Otherwise wrap the table.
$table.parent().append( $btn );
} );
var $parent = $table.parent();
var $target = /auto|scroll/.test( $parent.css( 'overflow-x' ) ) ? $parent : $table;

$target.wrap( '<div class="copy-table-wrapper">' );
$target.parent().append( $btn ); // button is now a sibling of the scroller
} );
} );
} );
}() );
}() );

Latest revision as of 20:32, 9 June 2026

/**
 * Gadget: CopyTable
 * Discreet copy icon at the bottom-right of every wikitable.
 * Copies content as TSV for pasting into Excel / Sheets.
 */
( function () {
    'use strict';

    // Standard two-rectangle "copy" icon
    var COPY_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" '
        + 'viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" '
        + 'stroke-linecap="round" stroke-linejoin="round">'
        + '<rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>'
        + '<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>'
        + '</svg>';

    // Checkmark shown after copy
    var CHECK_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" '
        + 'viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" '
        + 'stroke-linecap="round" stroke-linejoin="round">'
        + '<polyline points="20 6 9 17 4 12"/>'
        + '</svg>';

    function tableToTSV( table ) {
        var lines = [];
        $( table ).find( 'tr' ).each( function () {
            var cells = [];
            $( this ).find( 'th, td' ).each( function () {
                cells.push( $( this ).text().trim().replace( /[\t\n\r]+/g, ' ' ) );
            } );
            lines.push( cells.join( '\t' ) );
        } );
        return lines.join( '\n' );
    }

mw.hook( 'wikipage.content' ).add( function ( $content ) {
    $content.find( 'table.wikitable' ).not( '.copy-table-added' ).each( function () {
        var $table = $( this ).addClass( 'copy-table-added' );

        var $btn = $( '<button>' )
            .addClass( 'copy-table-btn' )
            .attr( 'title', 'Copy table' )
            .html( COPY_ICON )
            .on( 'click', function () {
                var tsv = tableToTSV( $table[ 0 ] );
                navigator.clipboard.writeText( tsv ).then( function () {
                    $btn.html( CHECK_ICON ).addClass( 'copy-table-btn--ok' );
                    setTimeout( function () {
                        $btn.html( COPY_ICON ).removeClass( 'copy-table-btn--ok' );
                    }, 2000 );
                } );
            } );

        // If the table sits in a horizontal-scroll box (the house style wraps it
        // in <div style="overflow-x:auto">), wrap THAT box so the button lives
        // OUTSIDE the scrolling area and stays pinned. Otherwise wrap the table.
        var $parent = $table.parent();
        var $target = /auto|scroll/.test( $parent.css( 'overflow-x' ) ) ? $parent : $table;

        $target.wrap( '<div class="copy-table-wrapper">' );
        $target.parent().append( $btn );   // button is now a sibling of the scroller
    } );
} );
}() );