MediaWiki:Gadget-copyTable.js: Difference between revisions
Content deleted Content added
Created page with "→* * Gadget: CopyTable * Adds a "Copy" button above every wikitable. * Copies content as TSV (tab-separated values) for pasting into Excel / Sheets.: 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' ) .text( '\uD83D\uDCCB..." |
No edit summary |
||
| (3 intermediate revisions by the same user not shown) | |||
Line 1:
/**
* Gadget: CopyTable
*
* Copies content as TSV
*/
'use strict';
$content.find( 'table.wikitable' ).not( '.copy-table-added' ).each( function () {▼
var $table = $( this ).addClass( 'copy-table-added' );▼
// Standard two-rectangle "copy" icon
var $btn = $( '<button>' )▼
var COPY_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" '
.addClass( 'copy-table-btn' )▼
+ 'viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" '
+ 'stroke-linecap="round" stroke-linejoin="round">'
.attr( 'title', 'Copy as tab-separated values' )▼
+ '<rect x="9" y="9"
+ '<path d="M5 15H4a2 2 0 0 1-2-2V4a2
navigator.clipboard.writeText( tsv ).then( function () {▼
// Checkmark shown after copy
setTimeout( function () {▼
var CHECK_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" '
$btn.text( '\uD83D\uDCCB Copy table' );▼
+ 'viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" '
}, 2000 );▼
+ 'stroke-linecap="round" stroke-linejoin="round">'
▲ } );
+ '<polyline points="20 6 9 17 4 12"/>'
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 ) {
$table.before( $btn );▼
// .chunkinfo: the narrow right-floated Chunk Info boxes (summary
▲ } );
// Phase 3) — the wrapper divs would break their float (text must
} );▼
// wrap around them), and TSV copy is pointless for annotation rows.
▲ $content.find( 'table.wikitable' ).not( '.copy-table-added' ).not( '.chunkinfo' ).each( function () {
▲ var $table = $( this ).addClass( 'copy-table-added' );
▲ var $btn = $( '<button>' )
▲ .addClass( 'copy-table-btn' )
.html( COPY_ICON )
.on( 'click', function () {
var tsv = tableToTSV( $table[ 0 ] );
▲ navigator.clipboard.writeText( tsv ).then( function () {
▲ setTimeout( function () {
$btn.html( COPY_ICON ).removeClass( 'copy-table-btn--ok' );
▲ }, 2000 );
} );
} );
// Two boxes: an inner .copy-table-scroll that scrolls horizontally, and a
▲function tableToTSV( table ) {
// non-scrolling .copy-table-wrapper that anchors the pinned button. The
▲ var lines = [];
// button is a SIBLING of the scroller (inside the wrapper), so it stays at
▲ $( table ).find( 'tr' ).each( function () {
// the visible top-right while the table scrolls underneath. If the table is
▲ var cells = [];
// already inside a scroll box, reuse that box as the scroller.
▲ $( this ).find( 'th, td' ).each( function () {
var $scroller;
if ( /auto|scroll/.test( $parent.css( 'overflow-x' ) ) ) {
$scroller = $parent;
} else {
$table.wrap( '<div class="copy-table-scroll">' );
$scroller = $table.parent();
}
$scroller.wrap( '<div class="copy-table-wrapper">' );
} );
▲ lines.push( cells.join( '\t' ) );
} );
▲}() );
▲ return lines.join( '\n' );
| |||