MediaWiki:Gadget-diff-info.js

Z Wikisłownika – wolnego słownika wielojęzycznego

Uwaga: aby zobaczyć zmiany po opublikowaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.

  • Firefox / Safari: Przytrzymaj Shift podczas klikania Odśwież bieżącą stronę, lub naciśnij klawisze Ctrl+F5, lub Ctrl+R (⌘-R na komputerze Mac)
  • Google Chrome: Naciśnij Ctrl-Shift-R (⌘-Shift-R na komputerze Mac)
  • Internet Explorer / Edge: Przytrzymaj Ctrl, jednocześnie klikając Odśwież, lub naciśnij klawisze Ctrl+F5
  • Opera: Naciśnij klawisze Ctrl+F5.
/**
 * Wyświetla dymek wskazujący liczbę zmodyfikowanych linii w danej zmianie,
 * najechawszy kursorem na odpowiedni element w widoku historii hasła, ostatnich
 * zmian lub wkładu użytkownika. Pomija zmiany tworzące nową stronę.
 * 
 * TODO:
 * - obsługa listy stron obserwowanych (+ inne?)
 * - obsługa zagnieżdżonych zmian na rozszerzonych OZ
 * - pomija zmiany na OZ zagnieżdżone wewnątrz tr.mw-enhanced-watched
 * - uniknąć wysyłania zapytań dla pierwszej wersji strony w historii zmian
 * - współpraca z Suwakiem Wersji (funkcja eksperymentalna)
 * 
 * @author [[User:Peter Bowman]]
 */

var messages = {
		'diff-info-lines-modified': '{{PLURAL:$1|$1 linia zmieniona|$1 linie zmienione|$1 linii zmienionych}}',
		'diff-info-lines-added': '{{PLURAL:$1|$1 linia dodana|$1 linie dodane|$1 linii dodanych}}',
		'diff-info-lines-deleted': '{{PLURAL:$1|$1 linia usunięta|$1 linie usunięte|$1 linii usuniętych}}'
	},
	config = mw.config.get( [
		'wgAction',
		'wgCanonicalSpecialPageName'
	] ),
	modules = [
		'mediawiki.util',
		'mediawiki.jqueryMsg',
		'mediawiki.api',
		'oojs-ui-core'
	],
	diffQuery = {
		formatversion: 2,
		action: 'compare',
		torelative: 'prev',
		prop: [ 'diff', 'ids' ]
	},
	API_DELAY = 100,
	api = null;

function extractOldid( $el ) {
	var $test;
	
	// historia zmian w hasłach
	$test = $el.siblings( 'input[name="oldid"]' );
	
	if ( $test.length ) {
		return $test.val();
	}
	
	// wkład użytkownika
	$test = $el.siblings( 'a.mw-changeslist-date' );
	
	if ( $test.length ) {
		return mw.util.getParamValue( 'oldid', $test.attr( 'href' ) );
	}
	
	// ostatnie zmiany (rozszerzone)
	$test = $el.siblings( '.mw-enhanced-rc-time' ).children( 'a' );
	
	if ( $test.length ) {
		return mw.util.getParamValue( 'oldid', $test.attr( 'href' ) );
	}
	
	// ostatnie zmiany (podstawowe)
	$test = $el.siblings( 'a[href]' ).filter( function ( i, el ) {
		return mw.util.getParamValue( 'diff', el.href ) !== null;
	} );
	
	if ( $test.length ) {
		return mw.util.getParamValue( 'diff', $test.first().attr( 'href' ) );
	}
	
	return null;
}

function makeRequest( oldid ) {
	return api.get( $.extend( {}, diffQuery, {
		fromrev: oldid
	} ) );
}

function analyzeDiffTable( $html ) {
	var info = {
		modified: 0,
		added: 0,
		deleted: 0
	};

	$html.filter( 'tr' ).each( function () {
		var $tr = $( this ),
			hasAddedLine = !!$tr.find( '.diff-addedline' ).length,
			hasDeletedLine = !!$tr.find( '.diff-deletedline' ).length;
		
		if ( hasAddedLine && hasDeletedLine ) {
			info.modified++;
		} else if ( hasAddedLine ) {
			info.added++;
		} else if ( hasDeletedLine ) {
			info.deleted++;
		}
	} );
	
	return info;
}

function makePopupContent( title, info ) {
	var $ul = $( '<ul>' );
	
	$.each( info, function ( key, value ) {
		if ( value !== 0 ) {
			$( '<li>' )
				.text( mw.msg( 'diff-info-lines-' + key, value ) )
				.appendTo( $ul );
		}
	} );
	
	return $( '<div>' ).append( [ title, $ul[ 0 ].outerHTML ] );
}

if (
	config.wgAction === 'history' ||
	[ 'Recentchanges', 'Contributions' ].indexOf( config.wgCanonicalSpecialPageName ) !== -1
) {
	mw.loader.using( modules ).done( function () {
		mw.messages.set( messages );
		api = new mw.Api();
		
		$( function () {
			$( '#pagehistory, .mw-changeslist, .mw-contributions-list' )
				.find( '.mw-plusminus-pos, .mw-plusminus-neg, .mw-plusminus-null' )
				.not( function () {
					var $el = $( this );
					
					return ( 
						$el.siblings( '.newpage' ).length ||
						//$el.siblings( '.mw-history-histlinks' ).children( 'a' ).length < 2 ||
						$el.closest( 'tr.mw-enhanced-rc, table.mw-enhanced-rc' ).find( '.newpage' ).length
					);
				} )
				.each( function () {
					var popup,
						$el = $( this ),
						oldid = extractOldid( $el );
					
					if ( !oldid ) {
						return true;
					}
					
					$el.data( 'title', $el.attr( 'title' ) ).removeAttr( 'title' );
					
					$el.on( 'mouseenter.diff', function ( evt ) {
						if ( popup ) {
							popup.toggle( true );
							return;
						}
						
						$el.data( 'diff-timer', setTimeout( function () {
							var request = makeRequest( oldid );
							
							$el
								.css( 'cursor', 'progress' )
								.data( 'diff-request', request )
								.removeData( 'diff-timer' );
							
							request.done( function ( res ) {
								var $body, info;
								
								$el.removeData( 'diff-request' );
								
								if ( !res.compare.hasOwnProperty( 'fromrevid' ) ) {
									$el
										.css( 'cursor', 'auto' )
										.attr( 'title', $el.data( 'title' ) );
									
									return;
								}
								
								$body = $( $.parseHTML( res.compare.body ) );
								info = analyzeDiffTable( $body );
								
								$el.css( 'cursor', 'help' );
								
								popup = new OO.ui.PopupWidget( {
									$content: makePopupContent( $el.data( 'title' ), info ),
									$floatableContainer: $el,
									padded: true,
									width: 250
								} );
								
								$( '#mw-content-text' ).append( popup.$element );
								popup.toggle( true );
								
								if ( $el.is( ':hover' ) ) {
									$el.trigger( 'mouseenter' );
								}
							} );
						}, API_DELAY ) );
					} );
					
					$el.on( 'mouseleave.diff', function ( evt ) {
						var timer = $el.data( 'diff-timer' ),
							request = $el.data( 'diff-request' );
						
						if ( timer !== undefined ) {
							clearTimeout( timer );
						}
						
						if ( request !== undefined ) {
							request.abort();
						}
						
						$el.removeData( [ 'diff-timer', 'diff-request' ] );
						
						if ( popup ) {
							popup.toggle( false );
						}
					} );
				} );
		} );
	} );
}