User:Ricordisamoa/WikidataTrust.js

From Wikidata
Jump to navigation Jump to search

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.
/* <nowiki>
 * WikidataTrust.js by [[User:Ricordisamoa]]
 * uses jQuery & Ajax
 *
 * inspired by the original WikiTrust (www.wikitrust.net) by the University of California, Santa Cruz
*/
/* global mw, $ */
$( document ).ready( function () {
	'use strict';

	var revisions, api, params, getRevisions;

	if ( !mw.config.exists( 'wbEntityId' ) ) {
		return;
	}
	if ( mw.config.get( 'wbEntityId' ) === 'L123' ) {
		console.log( 'WikidataTrust is disabled on L123 (see T349230)' );
		return;
	}

	revisions = [];
	api = new mw.Api();
	params = {
		prop: 'revisions',
		formatversion: 2,
		titles: mw.config.get( 'wgPageName' ),
		rvprop: 'content|user|ids',
		rvlimit: 'max',
		continue: ''
	};
	getRevisions = function ( cont ) {
		if ( cont ) {
			$.extend( params, cont );
		}
		return api.get( params )
		.then( function ( data ) {
			revisions = revisions.concat( data.query.pages[ 0 ].revisions );
			if ( data.continue ) {
				return getRevisions( data.continue );
			}
			return revisions;
		} );
	};
	getRevisions().done( function ( pages ) {
		var keySortReplacer,
			mapClaims, mapLabelsAndDescriptions, mapSitelinks, mapAliases,
			empty, validKeys, actions, parsedRevs,
			addLink, addLinkWithBr, addLinkLabel, addLinkDescription,
			addLinkAliases, addLinkSitelink, addLinkClaim;

		// from OOjs:
		// https://git.wikimedia.org/blob/oojs%2Fcore/bf2b8928b55cf6a637857131c2ad08a51a08864b/src%2Fcore.js#L399
		keySortReplacer = function ( key, val ) {
			var normalized, keys, i, len;
			if ( !Array.isArray( val ) && Object( val ) === val ) {
				// Normalize object keys
				normalized = {};
				keys = Object.keys( val ).sort();
				for ( i = 0, len = keys.length; i < len; i += 1 ) {
					normalized[ keys[ i ] ] = val[ keys[ i ] ];
				}
				return normalized;
			} else {
				return val;
			}
		};

		mapClaims = function ( claims ) {
			return $.map( claims, function ( claim ) {
				return JSON.stringify( claim, keySortReplacer );
			} );
		};

		mapLabelsAndDescriptions = function ( v, k ) {
			return k + ':' + v.value;
		};

		mapSitelinks = function ( v, k ) {
			return k + ':' + v.title + '|' + ( v.badges || [] ).join( '|' );
		};

		mapAliases = function ( aliases ) {
			return $.map( aliases, function ( alias ) {
				return alias.language + ':' + alias.value;
			} );
		};

		empty = {
			claims: [],
			sitelinks: [],
			labels: [],
			descriptions: [],
			aliases: []
		};
		validKeys = Object.keys( empty );
		actions = [];

		parsedRevs = $.map( pages, function ( rev ) {
			var ser, parsed;
			if ( rev !== undefined ) {
				ser = {
					user: rev.user
				};
				if ( rev.content === undefined ) {
					$.extend( ser, empty );
				} else {
					parsed = JSON.parse( rev.content );
					ser.claims = $.map( parsed.claims || [], mapClaims );
					ser.sitelinks = $.map( parsed.sitelinks || [], mapSitelinks );
					ser.labels = $.map( parsed.labels || [], mapLabelsAndDescriptions );
					ser.descriptions = $.map( parsed.descriptions || [], mapLabelsAndDescriptions );
					ser.aliases = $.map( parsed.aliases || [], mapAliases );
				}
				return ser;
			}
		} );

		addLink = function ( user, $userLink, $el, func, css ) {
			var $attrib, $sameLinks;
			if ( $el.find( '.wikidata_trust-author' ).length === 0 ) {
				func(
					$( '<small>' )
					.addClass( 'wikidata_trust-author' )
					.css( css || { 'margin-left': '2em' } )
					.text( 'by ' )
					.append( $userLink.clone( true ) )
				);
			} else {
				$attrib = $el.find( '.wikidata_trust-author' );
				$sameLinks = $attrib.find( 'a' ).filter( function () {
					return $( this ).text() === user;
				} );
				if ( $sameLinks.length === 0 ) {
					$attrib
					.append( ' and ' )
					.append( $userLink.clone( true ) );
				}
			}
		};

		addLinkWithBr = function ( user, $userLink, $el, css ) {
			addLink( user, $userLink, $el, function ( arg ) {
				return $el.append( '<br/>' ).append( arg );
			}, css );
		};

		addLinkLabel = function ( user, $userLink, e ) {
			var lang = e.split( ':' )[ 0 ],
			$el = $( '.wikibase-entityview[lang="' + lang + '"] .wb-firstHeading,' +
				'.wikibase-entitytermsforlanguageview-' + lang )
			.first()
			.find( '.wikibase-labelview-container' )
			.first();
			actions.unshift( [ addLinkWithBr, [ user, $userLink, $el ] ] );
		};

		addLinkDescription = function ( user, $userLink, e ) {
			var lang = e.split( ':' )[ 0 ],
			$el = $( '.wikibase-entityview[lang="' + lang +
				'"] .wb-firstHeading+.wikibase-descriptionview,' +
				'.wikibase-entitytermsforlanguageview-' + lang )
			.first()
			.find( '.wikibase-descriptionview-container' )
			.first();
			actions.unshift( [ addLinkWithBr, [ user, $userLink, $el ] ] );
		};

		addLinkAliases = function ( user, $userLink, e ) {
			var lang = e.split( ':' )[ 0 ],
			$el = $( '.wikibase-entitytermsforlanguageview-' + lang )
			.first()
			.find( '.wikibase-aliasesview-list' )
			.first();
			actions.unshift( [ addLinkWithBr, [ user, $userLink, $el ] ] );
		};

		addLinkSitelink = function ( user, $userLink, e ) {
			var $el = $( '.wikibase-sitelinkview.wikibase-sitelinkview-' + e.split( ':' )[ 0 ] )
				.children( '.wikibase-sitelinkview-link' ).last();
			actions.unshift( [ addLink, [ user, $userLink, $el, function ( arg ) {
				return $el.css( 'width', '100%' ).append( arg );
			}, { float: 'right' } ] ] );
		};

		addLinkClaim = function ( user, $userLink, claim ) {
			var id = JSON.parse( claim ).id,
			$el = $( '.wikibase-statementview' )
			.filter( function () {
				return $( this ).hasClass( 'wikibase-statement-' + id );
			} )
			.parents( '.wikibase-statementgroupview' ).first().find( '.wikibase-statementgroupview-property-label' ).first();
			if ( $el.find( '.wikidata_trust-author' ).length === 0 ) {
				actions.unshift( [ addLinkWithBr, [ user, $userLink, $el, {} ] ] );
			} else {
				actions.unshift( [ addLink, [ user, $userLink, $el ] ] );
			}
		};

		$.each( parsedRevs, function ( currIndex, curr ) {
			var prev, userName, $userLink,
				news = {};
			if ( currIndex < parsedRevs.length - 1 && parsedRevs[ currIndex + 1 ] !== undefined ) {
				prev = parsedRevs[ currIndex + 1 ];
			} else {
				prev = empty;
			}
			$.each( validKeys, function ( index, key ) {
				news[ key ] = $( curr[ key ] ).not( prev[ key ] ).get();
			} );

			userName = curr.user;

			$userLink = $( '<a>' )
			.text( userName )
			.attr( 'href', mw.util.getUrl(
				( mw.util.isIPAddress( userName ) ? 'Special:Contributions/' : 'User:' ) +
				userName
			) );

			$.each( news.labels, function ( i, e ) {
				addLinkLabel( userName, $userLink, e );
			} );

			$.each( news.descriptions, function ( i, e ) {
				addLinkDescription( userName, $userLink, e );
			} );

			$.each( news.aliases, function ( i, e ) {
				addLinkAliases( userName, $userLink, e );
			} );

			$.each( news.sitelinks, function ( i, e ) {
				addLinkSitelink( userName, $userLink, e );
			} );

			$.each( news.claims, function ( i, claim ) {
				addLinkClaim( userName, $userLink, claim );
			} );

			// TODO: removed sitelinks/claims?
		} );

		$.each( actions, function ( actionIndex, action ) {
			action[ 0 ].apply( null, action[ 1 ] );
		} );
	} );
} );