MediaWiki:Gadget-Global-LinkedPagesWithTemplates.js

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.
/**
 * This gadget produces a list of pages linked from a given page with one or more given templates
 */
const LinkedPagesWithTemplates = {

	init: function () {
		$( '.LinkedPagesWithTemplates' ).each( LinkedPagesWithTemplates.getPages );
	},

	getPages: function () {
		const $div = $( this );
		const page = $div.data( 'page' );
		if ( !page ) {
			$div.addClass( 'error' ).text( 'Param "page" is required' );
			return;
		}
		const templates = $div.data( 'templates' );
		if ( !templates ) {
			$div.addClass( 'error' ).text( 'Param "templates" is required' );
			return;
		}
		const params = {
			action: 'query',
			titles: page,
			prop: 'templates',
			tltemplates: templates.split( ',' ).map( template => 'Template:' + template ).join( '|' ),
			tllimit: 'max',
			generator: 'links',
			gpllimit: 'max',
			redirects: true,
			formatversion: 2,
		};
		// Remove empty params
		for ( const param in params ) {
			const value = params[ param ];
			if ( value === null || value === '' ) {
				delete params[ param ];
			}
		}
		const pages = [];
		new mw.Api().get( params ).fail( console.log ).done( response => LinkedPagesWithTemplates.getPagesContinue( response, params, pages, $div ) );
	},

	getPagesContinue: function ( response, params, pages, $div ) {
		for ( const page of response.query.pages ) {
			if ( page.templates ) {
				pages.push( page.title );
			}
		}
		if ( response.continue ) {
			params.gplcontinue = response.continue.gplcontinue;
			new mw.Api().get( params ).fail( console.log ).done( response => LinkedPagesWithTemplates.getPagesContinue( response, params, pages, $div ) );
		} else {
			LinkedPagesWithTemplates.makeList( pages, $div );
		}
	},

	makeList: function ( pages, $div ) {

		// Shuffle the results
		LinkedPagesWithTemplates.shuffle( pages );

		// Trim the results
		const limit = $div.data( 'limit' );
		if ( limit ) {
			pages = pages.slice( 0, limit );
		}

		// Make the list
		const $list = $( '<ul></ul>' );
		const editlink = $div.data( 'editlink' );
		const editintro = $div.data( 'editintro' );
		for ( const page of pages ) {
			const url = mw.util.getUrl( page );
			const $link = $( '<a target="_blank" href="' + url + '">' + page + '</a>' );
			const $item = $( '<li></li>' ).append( $link );
			if ( editlink ) {
				const editurl = mw.util.getUrl( page, { veaction: 'edit', editintro: editintro } );
				const $editicon = $( '<img width="14" height="14" src="https://upload.wikimedia.org/wikipedia/commons/3/3d/Pencil_edit_icon.svg" />' ).css( 'vertical-align', 'initial' );
				const $editlink = $( '<a target="_blank" href="' + editurl + '"></a>' ).css( 'margin-left', '.5em' ).append( $editicon );
				$item.append( $editlink );
			}
			$list.append( $item );
		}

		// Add it to the DOM
		$div.html( $list );
	},

	/**
	 * Helper method to shuffle an array
	 * Credit: https://stackoverflow.com/a/12646864/809356
 	 */
	shuffle: function ( array ) {
		for ( let i = array.length - 1; i > 0; i-- ) {
			const j = Math.floor( Math.random() * ( i + 1 ) );
			[ array[i], array[j] ] = [ array[j], array[i] ];
		}
	}
};

$( LinkedPagesWithTemplates.init );