MediaWiki:Common.js
MediaWiki interface page
More actions
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* Pwani 2050: on the projects category, draw a grid of photo tiles per theme in place of the
alphabetical listing. The category page carries an empty .okc-project-tiles marker with the
plan's themes in order (generated from the topic schema); each tile shows the page title, the
short name, over its {{Hero}} image, with the {{Infobox project}} theme and counties above it
and the infobox's full name on hover. Styles are in MediaWiki:Common.css,
which also hides the listing while the tiles load; if they cannot load, the listing comes back. */
( function () {
var marker = document.querySelector( '#mw-content-text .okc-project-tiles' );
if ( !marker || mw.config.get( 'wgAction' ) !== 'view' ) {
return;
}
var content = document.getElementById( 'mw-content-text' );
var category = mw.config.get( 'wgPageName' );
var themes = ( marker.getAttribute( 'data-themes' ) || '' ).split( '|' ).filter( Boolean );
// Theme names are accepted in any case, with "and" or "&" and with hyphens, as the infobox does.
function norm( s ) {
return s.toLowerCase().replace( /&/g, ' and ' ).replace( /[-_\s]+/g, ' ' ).trim();
}
var themeByNorm = {};
themes.forEach( function ( t ) {
themeByNorm[ norm( t ) ] = t;
} );
// One parameter from the first call of a template, with links reduced to their text.
function param( text, template, name ) {
var call = text.match( new RegExp( '\\{\\{\\s*' + template + '\\s*\\|([\\s\\S]*?)\\}\\}', 'i' ) );
if ( !call ) {
return '';
}
var m = call[ 1 ].match( new RegExp( '(?:^|\\|)\\s*' + name + '\\s*=([^|]*)', 'i' ) );
return m ? m[ 1 ].replace( /\[\[(?:[^|\]]*\|)?([^\]]*)\]\]/g, '$1' ).trim() : '';
}
function fetchAll( api, params, collect ) {
return api.get( params ).then( function ( data ) {
collect( data );
if ( data.continue ) {
return fetchAll( api, $.extend( {}, params, data.continue ), collect );
}
} );
}
function fail() {
content.classList.add( 'okc-project-tiles-failed' );
}
mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ).then( function () {
var api = new mw.Api();
var projects = [];
return fetchAll( api, {
action: 'query',
formatversion: 2,
generator: 'categorymembers',
gcmtitle: category,
gcmnamespace: 0,
gcmlimit: 50,
prop: 'revisions',
rvprop: 'content',
rvslots: 'main'
}, function ( data ) {
( data.query && data.query.pages || [] ).forEach( function ( p ) {
var text = p.revisions ? p.revisions[ 0 ].slots.main.content : '';
var theme = param( text, 'Infobox project', 'theme' );
projects.push( {
title: p.title,
name: param( text, 'Infobox project', 'name' ) || p.title,
theme: themeByNorm[ norm( theme ) ] || theme,
counties: param( text, 'Infobox project', 'counties' ),
image: param( text, 'Hero', 'image' ).replace( /^(File|Image):/i, '' ),
position: param( text, 'Hero', 'position' ).toLowerCase()
} );
} );
} ).then( function () {
var files = projects.filter( function ( p ) {
return p.image;
} ).map( function ( p ) {
return 'File:' + p.image;
} );
var thumbs = {};
var batches = [];
for ( var i = 0; i < files.length; i += 50 ) {
batches.push( api.get( {
action: 'query',
formatversion: 2,
titles: files.slice( i, i + 50 ),
prop: 'imageinfo',
iiprop: 'url',
iiurlwidth: 800
} ).then( function ( data ) {
var q = data.query || {};
var canon = {};
( q.normalized || [] ).forEach( function ( n ) {
canon[ n.to ] = n.from;
} );
( q.pages || [] ).forEach( function ( p ) {
if ( p.imageinfo ) {
thumbs[ canon[ p.title ] || p.title ] = p.imageinfo[ 0 ].thumburl || p.imageinfo[ 0 ].url;
}
} );
} ) );
}
return $.when.apply( $, batches ).then( function () {
render( projects, thumbs );
} );
} );
} ).catch( fail );
function render( projects, thumbs ) {
if ( !projects.length ) {
fail();
return;
}
var groups = {};
projects.forEach( function ( p ) {
var key = p.theme || '';
( groups[ key ] = groups[ key ] || [] ).push( p );
} );
var order = themes.filter( function ( t ) {
return groups[ t ];
} );
Object.keys( groups ).sort().forEach( function ( k ) {
if ( order.indexOf( k ) === -1 && k ) {
order.push( k );
}
} );
if ( groups[ '' ] ) {
order.push( '' );
}
marker.textContent = '';
order.forEach( function ( theme ) {
var section = document.createElement( 'section' );
section.className = 'okc-tiles-group';
var h = document.createElement( 'h2' );
if ( theme ) {
var link = document.createElement( 'a' );
link.href = mw.util.getUrl( theme );
link.textContent = theme;
h.appendChild( link );
} else {
h.textContent = 'No theme yet';
}
section.appendChild( h );
var grid = document.createElement( 'div' );
grid.className = 'okc-tiles';
groups[ theme ].sort( function ( a, b ) {
return a.title.localeCompare( b.title );
} ).forEach( function ( p ) {
var tile = document.createElement( 'a' );
tile.className = 'okc-tile';
tile.href = mw.util.getUrl( p.title );
tile.title = p.name;
var src = p.image && thumbs[ 'File:' + p.image ];
if ( src ) {
tile.style.backgroundImage = 'url("' + src.replace( /"/g, '%22' ) + '")';
tile.style.backgroundPosition = 'center ' +
( p.position === 'top' || p.position === 'bottom' ? p.position : 'center' );
}
var meta = document.createElement( 'span' );
meta.className = 'okc-tile-meta';
meta.textContent = [ p.theme, p.counties ].filter( Boolean ).join( ' · ' );
var name = document.createElement( 'span' );
name.className = 'okc-tile-name';
name.textContent = p.title;
tile.appendChild( meta );
tile.appendChild( name );
grid.appendChild( tile );
} );
section.appendChild( grid );
marker.appendChild( section );
} );
content.classList.add( 'okc-project-tiles-ready' );
}
}() );