User:Petr Matas/AnimatedHistory.js

From Meta, a Wikimedia project coordination wiki

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.
// Documentation is at [[User:Petr Matas/AnimatedHistory]]

(function () {
	if (mw.config.get('wgCanonicalNamespace') !== 'File') return;
	mw.loader.load('//meta.wikimedia.org/w/index.php?title=User:Petr_Matas/AnimatedHistory.css&action=raw&ctype=text/css', 'text/css');

	var img = $('.fullImageLink#file a img').first(),
		origwidth = img.width(),
		origheight = img.height(),
		imageinfo = [ ],
		info,
		api = new mw.Api(),
		cont = { },
		rev = 0,
		reqRev = 0;

	load().done(function () {
		if (imageinfo.length <= 1) return;
		
		$('<div class="animatedHistory-panel">')
		.append($('<button>&lt;</button>').click(1, changeRev))
		.append($('<button>&gt;</button>').click(-1, changeRev))
		.append(info = $('<span class="info">'))
		.insertAfter(img.closest('a'));
		
		loaderImg();
	});

	function load() {
		var	defer = $.Deferred(),
			count = imageinfo.length;
		if (cont) {
			api.get(
				$.extend({
					action: 'query',
					titles: mw.config.get('wgPageName'),
					prop: 'imageinfo',
					iilimit: 50,
					iiprop: 'timestamp|user|parsedcomment|url',
					iiurlwidth: img.width(),
					iiurlheight: img.height(),
				}, cont)
			)
			.done(function (data) {
				if (count !== imageinfo.length) return;
				Array.prototype.push.apply(imageinfo, data.query.pages[mw.config.get('wgArticleId') || -1].imageinfo);
				cont = data.continue;
				defer.resolve();
			});
		}
		return defer.promise();
	}

	function changeRev(e) {
		reqRev = rev + e.data;
		showRev();
	}
	
	function showRev() {
		if ( ! cont) reqRev = Math.min(reqRev, imageinfo.length - 1);
		reqRev = Math.max(reqRev, 0);
		updateOpacity();
		if (reqRev === rev) return;
		if (reqRev >= imageinfo.length) {
			load().done(showRev);
			return;
		}
		
		rev = reqRev;
		
		for (i = rev - 1; i <= rev + 1; i++) {
			if (i >= 0 && i < imageinfo.length) loaderImg(i);
		}

		img
		.attr('src', imageinfo[rev].thumburl)
		.width(imageinfo[rev].thumbwidth)
		.height(imageinfo[rev].thumbheight)
		.closest('a').attr('href', imageinfo[rev].url);
		
		updateOpacity();

		info.html(
			'<span class="date">' + imageinfo[rev].timestamp + '</span>\
			<span class="author">' + imageinfo[rev].user + '</span>\
			<span class="comment">' + imageinfo[rev].parsedcomment + '</span>'
		);
		
		if (rev === 0) $('.mw-filepage-resolutioninfo').show();
		else           $('.mw-filepage-resolutioninfo').hide();
		
		if (mw.config.get('wgArticleId')) { // this avoids linking to users from a different site
			var queriedRev = rev;
			api.get({
				action: 'parse',
				summary: '[[User:' + imageinfo[rev].user + '|' + imageinfo[rev].user +']]',
			})
			.done(function (data) {
				if (queriedRev === rev) {
					info.find('.author').html(data.parse.parsedsummary['*']);
				}
			});
		}
	}
	
	function loaderImg(forRev = rev) {
		var result = imageinfo[forRev].loaderImg;
		if (result) return result;
		result = imageinfo[forRev].loaderImg = new Image();
		result.src = imageinfo[forRev].thumburl;
		result.addEventListener("load", updateOpacity);
		return result;
	}
	
	function updateOpacity() {
		img.css('opacity', rev === reqRev && loaderImg().complete ? '' : 0.5);
	}
	
}) ();