MediaWiki:Gadget-references.js

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.
/**
 * @author: [[:pl:User:Beau]], [[:pl:User:Peter Bowman]]
 */

var referencesGadget = mw.libs.referencesGadget = {
		version: 17,
		categories: [],
		templates: {},
		gui: {},
		api: null
	},
	config = mw.config.get( [
		'wgNamespaceIds'
	] ),
	cacheOpts = {
		maxage: 28800,
		smaxage: 600
	},
	$wpTextbox = null,
	storageAutostartKey = 'ext.gadget.references.autostart',
	storageSelectionKey = 'ext.gadget.references.selection',
	API_DELAY = 100;

referencesGadget.fetchLanguages = function () {
	referencesGadget.api.get( $.extend( {
		formatversion: 2,
		list: 'categorymembers',
		cmlimit: 'max',
		cmprop: [ 'title', 'sortkeyprefix' ],
		cmnamespace: config.wgNamespaceIds.category,
		cmtitle: 'Kategoria:Szablony źródeł'
	}, cacheOpts ) )
	.done( referencesGadget.gotLanguages );
};

referencesGadget.gotLanguages = function ( response ) {
	response.query.categorymembers.forEach( function ( obj ) {
		var matches = obj.title.match( /\((.+?)\)$/ );
		
		if ( matches && obj.sortkeyprefix === matches[ 1 ] ) {
			referencesGadget.categories.push( { title: matches[ 1 ], name: obj.title } );
		}
	} );

	// sortuj nazwy
	referencesGadget.categories.sort( function ( a, b ) {
		return a.title.localeCompare( b.title, 'pl' );
	} );

	mw.libs.toolbarGadget.addButton( {
		icon: '//upload.wikimedia.org/wikipedia/commons/b/bf/Button_easy_cite_pl.png',
		title: mw.format( 'Wstawianie źródeł (wersja $1)', referencesGadget.version ),
		alt: 'Wstaw źródło',
		id: 'referencesGadgetButton',
		onclick: referencesGadget.showPanel
	} );
	
	if ( Number( mw.storage.get( storageAutostartKey ) ) ) {
		referencesGadget.showPanel();
	}
};

referencesGadget.fetchTemplates = function ( cmtitle, mainCategory ) {
	return referencesGadget.api.get( $.extend( {
		formatversion: 2,
		list: 'categorymembers',
		cmlimit: 'max',
		cmtitle: cmtitle,
		requestid: cmtitle
	}, cacheOpts ) )
	.then( function ( response ) {
		return referencesGadget.gotTemplates( mainCategory || cmtitle, response );
	} );
};

referencesGadget.gotTemplates = function ( mainCategory, response ) {
	var entry,
		templates = [],
		subcategories = [];

	response.query.categorymembers.forEach( function ( obj ) {
		switch ( obj.ns ) {
		case config.wgNamespaceIds.template:
			templates.push( obj.title.replace( /^Szablon:/, '' ) );
			break;
		case config.wgNamespaceIds.category:
			subcategories.push( obj.title );
			break;
		}
	} );
	
	if ( response.requestid !== mainCategory && mainCategory in referencesGadget.templates ) {
		entry = referencesGadget.templates[ mainCategory ];
	} else {
		entry = referencesGadget.templates[ mainCategory ] = [];
	}
	
	if ( templates.length ) {
		templates.sort( function ( a, b ) {
			return a.localeCompare( b, 'pl' );
		} );
		
		entry.push( {
			name: response.requestid,
			templates: templates
		} );
	}
	
	return $.when.apply( $, subcategories.filter( function ( name ) {
		return !(name in referencesGadget.templates);
	} ).map( function ( name ) {
		return referencesGadget.fetchTemplates( name, mainCategory );
	} ) );
};

referencesGadget.showPanel = function () {
	var selected;
	
	if ( referencesGadget.gui.$panel ) {
		referencesGadget.gui.$panel.toggle();
		mw.storage.set( storageAutostartKey, Number( referencesGadget.gui.$panel.is( ':visible' ) ) );
		return;
	}
	
	referencesGadget.gui.$panel = $( '<div>' )
		.addClass( 'references-panel' )
		.append( 'Język: ' );
	
	referencesGadget.gui.$select = $( '<select>' )
		.appendTo( referencesGadget.gui.$panel )
		.on( 'change', referencesGadget.changeLanguage );

	selected = mw.storage.get( storageSelectionKey );

	referencesGadget.categories.forEach( function ( obj ) {
		$( '<option>' )
			.val( obj.name )
			.prop( 'selected', obj.name === selected )
			.append( obj.title )
			.appendTo( referencesGadget.gui.$select );
	} );

	referencesGadget.gui.$links = $( '<div>' )
		.addClass( 'userSummaryButtons' )
		.appendTo( referencesGadget.gui.$panel )
		.on( 'click', 'a', referencesGadget.insertTemplate );

	$( '.wikiEditor-ui-bottom, #wpTextbox1' ).first().before( referencesGadget.gui.$panel );
	
	referencesGadget.changeLanguage.call( referencesGadget.gui.$select.get( 0 ) );
	
	mw.storage.set( storageAutostartKey, "1" );
};

referencesGadget.changeLanguage = function () {
	var option = this.options[ this.selectedIndex ],
		cmtitle = option.value;

	mw.storage.set( storageSelectionKey, cmtitle );

	if ( referencesGadget.templates[ cmtitle ] ) {
		referencesGadget.updateTemplateSelector( referencesGadget.templates[ cmtitle ] );
	} else {
		referencesGadget.fetchTemplates( cmtitle ).done( function () {
			referencesGadget.updateTemplateSelector( referencesGadget.templates[ cmtitle ] );
		} );
	}
};

referencesGadget.parseTemplate = function ( template ) {
	return referencesGadget.api.get( {
		formatversion: 2,
		titles: mw.format( 'Szablon:$1', template ),
		prop: 'extracts',
		exsentences: 10,
		explaintext: true
	} );
};

referencesGadget.updateTemplateSelector = function ( entry ) {
	referencesGadget.gui.$links.empty();
	
	entry.forEach( function ( obj, i ) {
		if ( i !== 0 ) {
			referencesGadget.gui.$links.append(
				'<hr>',
				obj.name.replace( /^Kategoria:/, '' ) + ': '
			);
		}
		
		obj.templates.forEach( function ( template ) {
			var $el = $( '<a>' )
				.append( template )
				.appendTo( referencesGadget.gui.$links )
				.after( ' ' );
			
			$el.on( 'mouseenter.popup-ref', function ( evt ) {
				if ( $el.attr( 'title' ) ) {
					return;
				}
				
				$el.data( 'timer-id', setTimeout( function () {
					var request = referencesGadget.parseTemplate( template );
					
					$el.data( 'request', request ).removeData( 'timer-id' );
					
					request.done( function ( res ) {
						var extract = res.query.pages[ 0 ].extract.replace( /\n(?:.|\n)*$/, '' );
						$el.removeData( 'request' ).attr( 'title', extract );
					} );
				}, referencesGadget.API_DELAY ) );
			} );
			
			$el.on( 'mouseleave.popup-ref', function ( evt ) {
				var timerID = $el.data( 'timer-id' ),
					request = $el.data( 'request' );
				
				if ( timerID !== undefined ) {
					clearTimeout( timerID );
				}
				
				if ( request !== undefined ) {
					request.abort();
				}
				
				$el.removeData( [ 'timer-id', 'request' ] );
			} );
		} );
	} );
};

referencesGadget.insertTemplate = function () {
	var content = this.textContent;
	
	if (
		window.customReferencesArgs &&
		typeof customReferencesArgs[ this.textContent ] === 'string'
	) {
		content += customReferencesArgs[ this.textContent ];
	}
	
	$wpTextbox.textSelection( 'encapsulateSelection', {
		pre: '<ref>{' + '{' + content,
		post: '}}</ref>'
	} );
	
	referencesGadget.tryInsertReferencesTag();
};

referencesGadget.tryInsertReferencesTag = function () {
	var refsField = '{{źródła}}',
		pos = $wpTextbox.textSelection( 'getCaretPosition', { startAndEnd: true } ), // [start, end]
		startPos = pos[ 0 ],
		txt = $wpTextbox.textSelection( 'getContents' ),
		refsIdx = txt.indexOf( refsField, startPos ),
		nextSection = txt.indexOf( '\n==', startPos );
	
	if (
		refsIdx !== -1 &&
		txt.slice( startPos, refsIdx ).indexOf( '\n==' ) === -1 &&
		txt.slice( refsIdx, nextSection !== -1 ? nextSection : txt.length ).search( /<references.*?>/i ) === -1
	) {
		$wpTextbox.textSelection( 'setContents',
			txt.slice( 0, refsIdx ) +
			refsField +
			'\n<references />' +
			txt.slice( refsIdx + refsField.length )
		);
		
		// hackish: first we ensure to scroll as much as possible while the beginning
		// of the selection is still visible
		$wpTextbox.textSelection( 'setSelection', { start: startPos, end: txt.length } );
		// then we (attempt to) restore the original selection
		$wpTextbox.textSelection( 'setSelection', { start: startPos, end: pos[ 1 ] } );
		// tested and not working properly:
		// * `$wpTextbox.scrollTop( initialScroll );` with `initialScroll = $wpTextbox.scrollTop();`,
		//    ignored in syntax highlighting mode
		// * `$wpTextbox.textSelection( 'scrollToCaretPosition' )`
	}
};

$( function () {
	$wpTextbox = $( '#wpTextbox1' );
	referencesGadget.api = new mw.Api();
	referencesGadget.fetchLanguages();
} );