User:Ans/Gadget-DuplicateReferences.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)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * Adds a link to copy references and add them to other statements on the same item.
 *
 * @see [[MediaWiki:Gadget-DuplicateReferences.css]]
 * @author Bene*, User:Ans
 */
( function ( $, mw, wb ) {
	'use strict';

	if ( !mw.config.exists( 'wbEntityId' ) ||
		!mw.config.get( 'wbIsEditView' ) ||
		!mw.config.get( 'wgIsProbablyEditable' )
	) {
		return;
	}

		mw.messages.set( {
			'save': 'save',
		} );
	switch ( mw.config.get( 'wgUserLanguage' ) ) {
	default:
	case 'en':
		mw.messages.set( {
			'insert-reference': 'insert reference',
			'save': 'save',
			'copy': 'copy',
			'saving': 'saving',
			'copied': 'copied',
			'insert-reference-failed': 'The reference could not be inserted.'
		} );
		break;
	case 'cs':
		mw.messages.set( {
			'insert-reference': 'vložit referenci',
			'copy': 'zkopírovat',
			'saving': 'ukládám',
			'copied': 'zkopírováno',
			'insert-reference-failed': 'Referenci nebylo možné uložit.'
		} );
		break;
	case 'de':
		mw.messages.set( {
			'insert-reference': 'Einzelnachweis einfügen',
			'copy': 'kopieren',
			'saving': 'speichern',
			'copied': 'kopiert',
			'insert-reference-failed': 'Der Einzelnachweis konnte nicht eingefügt werden.'
		} );
		break;
	case 'el':
		mw.messages.set( {
			'insert-reference': 'προσθήκη παραπομπής',
			'copy': 'αντιγραφή',
			'saving': 'αποθηκεύεται',
			'copied': 'αντιγράφτηκε',
			'insert-reference-failed': 'αποτυχημένη προσθήκη παραπομπής.'
		} );
		break;
	case 'fr':
		mw.messages.set( {
			'insert-reference': 'coller la référence',
			'copy': 'copier',
			'saving': 'enregistrement',
			'copied': 'copiée',
			'insert-reference-failed': 'La référence ne peut pas être collée.'
		} );
		break;
	case 'it':
		mw.messages.set( {
			'insert-reference': 'incolla riferimento',
			'copy': 'copia',
			'saving': 'copia in corso',
			'copied': 'copiato',
			'insert-reference-failed': 'il riferimento non può essere copiato'
		} );
		break;
	case 'mk':
		mw.messages.set( {
			'insert-reference': 'вметни навод',
			'copy': 'копирај',
			'saving': 'зачувувам',
			'copied': 'ископирано',
			'insert-reference-failed': 'Не можев да го вметнам наводот.'
		} );
		break;
	case 'nl':
		mw.messages.set( {
			'insert-reference': 'bron invoegen',
			'copy': 'kopiëren',
			'saving': 'opslaan',
			'copied': 'gekopieerd',
			'insert-reference-failed': 'De bron kon niet ingevoegd worden.'
		} );
		break;
	case 'th':
		mw.messages.set( {
			'insert-reference': 'วางการอ้างอิง',
			'save': 'บันทึก',
			'copy': 'คัดลอก',
			'saving': 'กำลังบันทึก',
			'copied': 'คัดลอกแล้ว',
			'insert-reference-failed': 'ไม่สามารถวางการอ้างอิง'
		} );
		break;
	}

/*
	Create model	
	This will create a model object for saving the reference.
	This can be removed once there is factory for getting StatementsChanger
*/

	function buildEntityStore( repoApi, languageCode ) {
		return new wb.store.CachingEntityStore(
			new wb.store.ApiEntityStore(
				repoApi,
				new wb.serialization.EntityDeserializer(),
				[ languageCode ]
			)
		);
	}

	function getUserLanguages() {
		var userLanguages = mw.config.get( 'wbUserSpecifiedLanguages' ),
			isUlsDefined = mw.uls && $.uls && $.uls.data,
			languages;

		if ( !userLanguages.length && isUlsDefined ) {
			languages = mw.uls.getFrequentLanguageList().slice( 1, 4 );
		} else {
			languages = userLanguages.slice();
			languages.splice( $.inArray( mw.config.get( 'wgUserLanguage' ), userLanguages ), 1 );
		}

		languages.unshift( mw.config.get( 'wgUserLanguage' ) );

		return languages;
	}

	var entityPromise = $.Deferred( function ( deferred ) {
		mw.hook( 'wikibase.entityPage.entityLoaded' ).add( function ( entity ) {
			deferred.resolve( entity );
		} );
	} ).promise();
	var entityInitializer = new wb.EntityInitializer( entityPromise );	
	var model = null;
	entityInitializer.getEntity().done( function ( entity ) {
		var repoConfig = mw.config.get( 'wbRepo' ),
		repoApiUrl = repoConfig.url + repoConfig.scriptPath + '/api.php',
		mwApi = wb.api.getLocationAgnosticMwApi( repoApiUrl ),
		repoApi = new wb.api.RepoApi( mwApi ),
		userLanguages = getUserLanguages(),
		entityStore = buildEntityStore( repoApi, userLanguages[ 0 ] ),
		revisionStore = new wb.RevisionStore( mw.config.get( 'wgCurRevisionId' ) ),
		entityChangersFactory = new wb.entityChangers.EntityChangersFactory(
			repoApi,
			revisionStore,
			entity
		);
		model = entityChangersFactory.getStatementsChanger();
	} );
	
/*
	/Create model	
*/

	var selectedReference = null;

	function insertReference( statementview ) {
		//var deferred = $.Deferred();

		if ( selectedReference !== null ) {
			var statement = statementview.value();
			selectedReference._hash = null; // set hash to null to create a new reference
			statement.getReferences().addItem( selectedReference );

			//model.save( statement ).done( function ( statement ) {
				if ( !statementview._referencesListview ) {
					statementview._createReferencesListview();
				}
				statementview._recreateReferences();
				//deferred.resolve();
			//} ).fail( function ( error ) {
			//	mw.notify( error.getMessage(), {
			//		title: mw.msg( 'insert-reference-failed' ),
			//		type: 'error'
			//	} );
			//	deferred.resolve();
			//} );
		}

		//return deferred.promise();
	}

	function saveStatement( statementview ) {
		var deferred = $.Deferred();

		if ( selectedReference !== null ) {
			var statement = statementview.value();

			model.save( statement ).done( function ( statement ) {
				if ( !statementview._referencesListview ) {
					statementview._createReferencesListview();
				}
				statementview._recreateReferences();
				deferred.resolve();
			} ).fail( function ( error ) {
				mw.notify( error.getMessage(), {
					title: mw.msg( 'insert-reference-failed' ),
					type: 'error'
				} );
				deferred.resolve();
			} );
		}

		return deferred.promise();
	}

	function selectReference( ref ) {
		selectedReference = ref;
		//selectedReference._hash = null; // set hash to null to create a new reference

		if ( $( '.wikibase-toolbar-button-insert' ).length === 0 ) {
			addInsertLinks();
		}
	}

	function addInsertLinks() {
		// [insert reference]
		$( '.wikibase-statementview-references .wikibase-toolbar-button-add' ).after(
			$( '<span>' )
			//.addClass( 'wikibase-toolbarbutton wikibase-toolbar-item wikibase-toolbar-button wikibase-toolbar-button-insert' )
			.addClass( 'wikibase-toolbarbutton wikibase-toolbar-item wikibase-toolbar-button' )
			.append(
				$( '<a>' )
				.addClass( 'wikibase-toolbar-button-insert' )
				.attr( 'href', '#' )
				.text( mw.msg( 'insert-reference' ) )
				.prepend( $( '<span>' ).addClass( 'wb-icon' ) )
				.click( function ( e ) {
					e.preventDefault();
					var $this = $( this ),
						$parent = $this.parent();

					if ( !$parent.hasClass( 'wikibase-toolbarbutton-disabled' ) ) {
						//$parent.addClass( 'wikibase-toolbarbutton-disabled ui-state-disabled' );
						//$this.text( mw.msg( 'saving' ) ).prepend( $( '<span>' ).addClass( 'wb-icon' ) );

						var statementview = $this.parents( '.wikibase-statementview' ).data( 'statementview' );
						insertReference( statementview )/*.done( function () {
							$parent.removeClass( 'wikibase-toolbarbutton-disabled ui-state-disabled' );
							$this.text( mw.msg( 'insert-reference' ) ).prepend( $( '<span>' ).addClass( 'wb-icon' ) );
						} )*/;
					}
				} )
			)
			.append(
				$( '<a>' )
				.addClass( 'wikibase-toolbar-button-save' )
				.attr( 'href', '#' )
				.text( mw.msg( 'save' ) )
				.prepend( $( '<span>' ).addClass( 'wb-icon' ) )
				.click( function ( e ) {
					e.preventDefault();
					var $this = $( this ),
						$parent = $this.parent();

					if ( !$parent.hasClass( 'wikibase-toolbarbutton-disabled' ) ) {
						$parent.addClass( 'wikibase-toolbarbutton-disabled ui-state-disabled' );
						$this.text( mw.msg( 'saving' ) ).prepend( $( '<span>' ).addClass( 'wb-icon' ) );

						var statementview = $this.parents( '.wikibase-statementview' ).data( 'statementview' );
						saveStatement( statementview ).done( function () {
							$parent.removeClass( 'wikibase-toolbarbutton-disabled ui-state-disabled' );
							$this.text( mw.msg( 'save' ) ).prepend( $( '<span>' ).addClass( 'wb-icon' ) );
						} );
					}
				} )
			)
		);
	}

	function addCopyLinks( element ) {
		//hide existing items
		$( element ).find( '.wikibase-referenceview-heading' ).find( '.wikibase-toolbar-item' ).hide();
		// [copy]
		$( element ).find( '.wikibase-referenceview-heading' ).append(
			$( '<div>' )
			.addClass( 'wikibase-copytoolbar-container wikibase-toolbar-container' )
			.append(
				$( '<span>' )
				.addClass( 'wikibase-toolbarbutton wikibase-toolbar-item wikibase-toolbar-button wikibase-toolbar-button-copy' )
				.append(
					$( '<a>' )
					.attr( 'href', '#' )
					.text( mw.msg( 'copy' ) )
					.prepend( $( '<span>' ).addClass( 'wb-icon' ) )
					.click( function ( e ) {
						e.preventDefault();
						var $this = $( this ),
							$parent = $this.parent();

						if ( !$parent.hasClass( 'wikibase-toolbarbutton-disabled' ) ) {
							$( '.wikibase-toolbar-button-copy' )
								.removeClass( 'wikibase-toolbarbutton-disabled ui-state-disabled' )
								.find( 'a' )
								.text( mw.msg( 'copy' ) )
								.prepend( $( '<span>' ).addClass( 'wb-icon' ) );

							$parent.addClass( 'wikibase-toolbarbutton-disabled ui-state-disabled' );
							$this.text( mw.msg( 'copied' ) ).prepend( $( '<span>' ).addClass( 'wb-icon' ) );

							var hash = $this.closest( '.wikibase-referenceview' )[ 0 ].className.match( /wikibase-referenceview-([0-9a-z]+)/ )[ 1 ];
							var statement = $this.closest( '.wikibase-statementview' ).data( 'wikibase-statementview' ).value();
							selectReference( statement.getReferences().toArray().filter( function ( v ) { return v.getHash() === hash } )[ 0 ] );
						}
					} )
				)
			)
		);
	}

	$( function () {
		addCopyLinks( '.wikibase-statementview' );

		// remove [copy] when entering edit mode to avoid clashes
		$( document )
			.on( 'snakviewafterstartediting', function ( e ) {
				setTimeout( function () {
					$( e.target ).find( '.wikibase-referenceview-heading' ).find( '.wikibase-copytoolbar-container' ).remove();
					// show existing items
					$( e.target ).find( '.wikibase-referenceview-heading' ).find( '.wikibase-toolbar-item' ).show();
				}, 50 );			
			} )
			.on( 'snakviewafterstopediting', function ( e ) {
				var element = $( e.target ).parents( '.wikibase-statementview' );
				// ugly hack but there seems to be no proper event to add this
				setTimeout( function () {
					addCopyLinks( element );
				}, 50 );
			} );
	} );

} )( jQuery, mediaWiki, wikibase );