MediaWiki:Gadget-ChangesByLanguage.js

( [ "Recentchanges", "Watchlist", "Recentchangeslinked" ] ).indexOf( mw.config.get( "wgCanonicalSpecialPageName" ) ) !== -1 && $( function {	var diffLinksSelector = ".mw-changeslist .special li > .mw-changeslist-line-inner > a:first-child, .mw-enhanced-rc .mw-title + a, .mw-enhanced-rc-nested a[tabindex] + a";	var getRevisions = ( function  { var revRequests = {}, pRequests = {}; function sendRequests( requests, isPageid ) { var pendingReqs = []; $.each( requests, function ( i, req ) {				if ( !req.status ) {					pendingReqs.push( i );					req.status = 1;				}			} ); for ( var i = 0; i < pendingReqs.length; i += 50 ) { var query = { action: 'query', prop: 'revisions', rvprop: 'content|ids', maxage: 60 * 60 * 12, smaxage: 60 * 60 * 12 };				query[ isPageid ? 'pageids' : 'revids' ] = pendingReqs.slice( i, i + 50 ).join( '|' ); ( new mw.Api ).get( query ).done( function ( results ) {					$.each( results.query.pages, function ( id, revision ) { $.each( revision.revisions, function ( i, rev ) {							var rid = isPageid ? id : rev.revid,								result = requests[ rid ].result =									rev[ '*' ];							requests[ rid ].status = 2;							$.each( requests[ rid ], function ( i, callback ) { callback( result ); } );						} );					} );				} );			}		}		return function getRevisions( id, callback, isPageid ) { if ( id ) { var requests = isPageid ? pRequests : revRequests, req = requests[ id ] || ( requests[ id ] = [] ); if ( callback ) { if ( !req.status || req.status === 1 ) { req.push( callback ); } else { callback( req.result ); }				}			} else { sendRequests( pRequests, true ); sendRequests( revRequests, false ); }			return getRevisions; };	} );	function getSection( content, language ) {		var start = content.indexOf( '==' + language + '==' ),			end = content.substr( start ).search( /$|\n==[^=]/ );		if ( start === -1 ) {			return false;		} else {			return content				.substr( start, end )				// Don't count a new section being added below as a change.				.replace( /[\n \-]+$/g,  )				// Filter out translations sections.				.replace( /(\{\{(?:check)?trans-top[^\}]*\}\})[\s\S]*?(?=\{\{(?:check)?trans-bottom\}\})/g, '$1' );		}	}	function getTranslations( content, language ) {		var t = content			.match( new RegExp( '\n[\\*\\:]+\\s*' + language + ': [^\n]+', 'g' ) );		return t ? t.join( '\n' ) : ;	}	function getLanguage {		return languageData			.split( /\s*[,|]\s*/g)			// Remove empty strings			.filter( function ( x ) { return x; } );	}	function hideFiltered {		if ( !languages || !languages.length ) {			return;		}		$( diffLinksSelector ).each( function( i, diffLink ) { var href = diffLink.href, oldid = mw.util.getParamValue( "oldid", href ), curid = mw.util.getParamValue( "diff", href ), title = mw.util.getParamValue( "title", href ); if ( title && !title.includes( ":" ) && oldid && curid ) { getRevisions( curid ); getRevisions( oldid, function ( oldRevision ) {					getRevisions( curid, function ( curRevision ) { var show = languages.some( function ( language ) {							var oldSection = getSection( oldRevision, language ),								newSection = getSection( curRevision, language );							if ( oldSection !== newSection ) {								return true;							} else if ( getTranslations( oldRevision, language ) !== getTranslations( curRevision, language ) ) {								return true;							}						} ); if ( !show ) { diffLink.parentNode.parentNode.style.display = 'none'; }					} );				} );			}		} );		// Newly created pages, without diff links.		$( '.newpage' ).prev.prev.each( function ( i, histLink ) { var href = histLink.href, curid = mw.util.getParamValue( "curid", href ); getRevisions( curid, function ( curRevision ) {				var show = languages.some( function ( language ) { if ( getSection( curRevision, language ) || getTranslations( curRevision, language ) ) { return true; }				} );				if ( !show ) {					histLink.parentNode.parentNode.style.display = 'none';				}			}, true ); } );		// Send the API requests.		getRevisions;	}	function showAll {		$( '.mw-changeslist .special li' ).show;	}	// Settings	var options = document.querySelector( "#mw-watchlist-options, .rcoptions, .mw-rcfilters-head" ),		optionsDiv = document.createElement( "div" ),		input, 		languages,		languageData,		isEnhanced = $( '.mw-enhanced-rc, .mw-rcfilters-head' ).length;	if ( options ) {		options.appendChild( document.createElement( "hr" ) ).style.margin = "8px 0";		if ( isEnhanced ) {			// If "Enhanced recent changes" is enabled, this script doesn't work.			optionsDiv.appendChild( document.createTextNode( '(The "Recent changes by language" gadget requires the "Use non-JavaScript interface" preference to be ON and the "Group changes by page" preference to be OFF.)' ) );			options.appendChild( optionsDiv );		} else {			optionsDiv.appendChild( document.createTextNode( 'Languages: ' ) );			input = optionsDiv.appendChild( document.createElement( 'input' ) );			languageData = ( input.value = ( localStorage[ 'YR-rcbl' ] || '' ) );			languages = getLanguage;			input.onkeydown = input.onkeyup = function ( e ) {				languageData = localStorage[ 'YR-rcbl' ] = this.value;				if ( e.keyCode === 13 && e.type === 'keydown' ) {					languages = getLanguage;					showAll;					hideFiltered;					e.preventDefault && e.preventDefault;					return false;				}			};			input.onblur = function {				languageData = localStorage[ 'YR-rcbl' ] = this.value;				languages = getLanguage;				showAll;				hideFiltered;			};			options.appendChild( optionsDiv );			// Run			hideFiltered;		}	} } );