MediaWiki:Gadget-Gallery.js
外观
注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5。
/**
* Gallery gadget — Instagram-style image gallery with drag-and-drop upload.
* Powers the full 图库 page and the homepage mini-widget.
*/
( function () {
'use strict';
var CAT = 'Category:图库';
var PAGE_NAME = '图库';
var api = new mw.Api();
/* ── Fetch images from the 图库 category ─────────────────────── */
function fetchImages( limit, cb ) {
api.get( {
action: 'query',
generator: 'categorymembers',
gcmtitle: CAT, gcmtype: 'file',
gcmlimit: limit, gcmsort: 'timestamp', gcmdir: 'descending',
prop: 'imageinfo',
iiprop: 'url|dimensions|timestamp',
iiurlwidth: 400,
format: 'json'
} ).done( function ( data ) {
if ( !data.query || !data.query.pages ) { cb( [] ); return; }
var pages = Object.values( data.query.pages ).filter( function ( p ) {
return p.imageinfo && p.imageinfo[ 0 ];
} );
pages.sort( function ( a, b ) {
return b.imageinfo[ 0 ].timestamp.localeCompare( a.imageinfo[ 0 ].timestamp );
} );
cb( pages );
} ).fail( function () { cb( [] ); } );
}
/* ── Build one grid item (works for both full and widget grids) ─ */
function makeItem( page, cls ) {
var info = page.imageinfo[ 0 ];
var thumb = info.thumburl || info.url;
var title = page.title; // "File:foo.jpg"
var href = mw.util.getUrl( title );
var a = document.createElement( 'a' );
a.href = href;
a.className = cls + ' image'; // "image" lets MultimediaViewer intercept
a.title = title.replace( /^(File|文件):/, '' );
var img = document.createElement( 'img' );
img.src = thumb;
img.alt = a.title;
img.loading = 'lazy';
a.appendChild( img );
return a;
}
/* ════════════════════════════════════════════════════════════════
FULL GALLERY PAGE
════════════════════════════════════════════════════════════════ */
function initFullGallery() {
var root = document.getElementById( 'mw-gallery-root' );
if ( !root ) { return; }
var groups = mw.config.get( 'wgUserGroups' ) || [];
var canUpload = groups.indexOf( 'user' ) !== -1 || groups.indexOf( 'sysop' ) !== -1;
/* Build skeleton */
if ( canUpload ) {
root.innerHTML =
'<div id="gal-drop">' +
' <div class="gal-drop-inner">' +
' <span class="gal-drop-icon">📷</span>' +
' <p>将图片拖放至此上传</p>' +
' <p class="gal-drop-sub">或 <label class="gal-browse">点击选择文件' +
' <input type="file" id="gal-file-input" multiple accept="image/*">' +
' </label></p>' +
' </div>' +
' <div id="gal-status"></div>' +
'</div>' +
'<div id="gal-grid" class="gal-grid"></div>';
} else {
root.innerHTML = '<div id="gal-grid" class="gal-grid"></div>';
}
var grid = document.getElementById( 'gal-grid' );
var status = document.getElementById( 'gal-status' );
function reload() {
grid.innerHTML = '<div class="gal-loading">加载中…</div>';
fetchImages( 200, function ( pages ) {
grid.innerHTML = '';
if ( pages.length === 0 ) {
grid.innerHTML = '<div class="gal-empty">还没有图片,快来上传第一张吧!</div>';
return;
}
pages.forEach( function ( p ) {
grid.appendChild( makeItem( p, 'gal-item' ) );
} );
} );
}
reload();
if ( !canUpload ) { return; }
/* ── Upload logic ─────────────────────────────────────────── */
var drop = document.getElementById( 'gal-drop' );
var input = document.getElementById( 'gal-file-input' );
drop.addEventListener( 'dragover', function ( e ) {
e.preventDefault(); drop.classList.add( 'gal-dragover' );
} );
drop.addEventListener( 'dragleave', function () {
drop.classList.remove( 'gal-dragover' );
} );
drop.addEventListener( 'drop', function ( e ) {
e.preventDefault();
drop.classList.remove( 'gal-dragover' );
uploadFiles( e.dataTransfer.files );
} );
input.addEventListener( 'change', function () { uploadFiles( input.files ); } );
function uploadFiles( fileList ) {
var files = Array.from( fileList );
var total = files.length, done = 0, failed = 0;
status.innerHTML = '<span class="gal-progress">上传中 0/' + total + '…</span>';
files.forEach( function ( file ) {
api.getToken( 'csrf' ).done( function ( token ) {
var fd = new FormData();
fd.append( 'action', 'upload' );
fd.append( 'format', 'json' );
fd.append( 'filename', file.name );
fd.append( 'file', file );
fd.append( 'token', token );
fd.append( 'ignorewarnings', '1' );
fd.append( 'text', '[[Category:图库]]\n上传自图库。' );
fd.append( 'comment', '图库上传' );
fetch( mw.config.get( 'wgScriptPath' ) + '/api.php', {
method: 'POST', body: fd, credentials: 'same-origin'
} )
.then( function ( r ) { return r.json(); } )
.then( function ( res ) {
done++;
if ( !res.upload || res.upload.result !== 'Success' ) { failed++; }
var msg = done < total
? '上传中 ' + done + '/' + total + '…'
: ( failed
? '完成,' + failed + ' 张失败'
: '✓ 全部上传完成!' );
status.innerHTML = '<span class="' +
( done === total && !failed ? 'gal-ok' : 'gal-progress' ) +
'">' + msg + '</span>';
if ( done === total ) { reload(); }
} )
.catch( function () {
done++; failed++;
status.innerHTML = '<span class="gal-err">上传出错,请重试</span>';
} );
} );
} );
}
}
/* ════════════════════════════════════════════════════════════════
HOMEPAGE MINI WIDGET
════════════════════════════════════════════════════════════════ */
function initWidget() {
var root = document.getElementById( 'mw-gallery-widget' );
if ( !root ) { return; }
root.innerHTML = '<div class="gal-widget-grid"></div>' +
'<a href="' + mw.util.getUrl( PAGE_NAME ) + '" class="gal-widget-more">查看全部 →</a>';
var grid = root.querySelector( '.gal-widget-grid' );
fetchImages( 8, function ( pages ) {
if ( pages.length === 0 ) {
root.innerHTML = '<p class="gal-widget-empty">图库暂无图片</p>' +
'<a href="' + mw.util.getUrl( PAGE_NAME ) + '">前往图库上传 →</a>';
return;
}
pages.slice( 0, 8 ).forEach( function ( p ) {
grid.appendChild( makeItem( p, 'gal-widget-item' ) );
} );
} );
}
$( function () {
if ( mw.config.get( 'wgPageName' ) === PAGE_NAME ) { initFullGallery(); }
initWidget();
} );
}() );