MediaWiki:Gadget-ChangesByLanguage.js

From Wiktionary, the free dictionary
Jump to navigation Jump to search

Note – after saving, you may have to bypass your browser’s cache to see the changes.

  • Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
  • Konqueror and Chrome: click Reload or press F5;
  • Opera: clear the cache in Tools → Preferences;
  • Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.

( [ "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();
		}
	}
} );