User:Jeblad/pageview2/script.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.
// Code to make a footer message about pageviews
// © John Erling Blad, Creative Commons by Attribution 3.0

// This needs slight editing if used as a gadget,
// ie. remove first and last line and make a line in [[MediaWiki:Gadgets-definition]]
// with the resource definition
mw.loader.using( ['mediawiki.api','jquery.makeCollapsible'], function () {
$(function( $content ) {
	"use strict";
	var days = 14;
	
	var conf = mw.config.get( [
		'wgUserLanguage',
		'wgNamespaceNumber',
		'wgServerName',
		'wgPageName'
	] );
	
	if ( conf.wgNamespaceNumber !== 0) {
		mw.log( "So wise so young, they say do never live long." );
		return;
	}
	
	var ajax = {
		'protocol': mw.Uri.protocol,
		'host': 'wikimedia.org',
		'path': '/api/rest_v1/metrics/pageviews/per-article'
	};
	
	var buildURI = function(ajax, opts) {
		var args = jQuery.extend({}, ajax, opts);
		var path = ajax.path.split('/');
		if (args.project === undefined) {
			args.project = conf.wgServerName;
		}
		if (/^[\w\.]*$/.test(args.project)) path.push(args.project);
		if (args.access === undefined) {
			args.access = 'all-access';
		}
		if (/^[-\w]*$/.test(args.access)) path.push(args.access);
		if (args.agents === undefined) {
			args.agents = 'all-agents';
		}
		if (/^[-\w]*$/.test(args.agents)) path.push(args.agents);
		if (args.pageName === undefined) {
			args.pageName = conf.wgPageName;
			path.push(args.pageName);
		}
		else {
			if (/^[-+_\w\s%]*$/i.test(args.pageName)) path.push(args.pageName);
		}
		if (args.granularity === undefined) {
			args.granularity = 'daily';
		}
		if (/^[\w]*$/.test(args.granularity)) path.push(args.granularity);
		var end = new Date();
		var start = new Date(end.valueOf()-(days+1)*24*60*60*1000);
		if (args.start === undefined) {
			args.start = ''
				+start.getUTCFullYear()
				+(start.getUTCMonth()<10 ? '0' : '')+(start.getUTCMonth()+1)
				+(start.getUTCDate()<10 ? '0' : '')+start.getUTCDate(); 
		}
		if (/^[\d]*$/i.test(args.start)) path.push(args.start);
		if (args.end === undefined) {
			args.end = ''
				+end.getUTCFullYear()
				+(end.getUTCMonth()<10 ? '0' : '')+(end.getUTCMonth()+1)
				+(end.getUTCDate()<10 ? '0' : '')+end.getUTCDate(); 
		}
		if (/^[\d]*$/i.test(args.end)) path.push(args.end);
		return new mw.Uri( jQuery.extend({}, args, { 'path': path.join('/')}) );
	};
	
	var stats = {
		count: 0,
		mean: 0,
		stdev: 0,
		mean2: 0,
		stdev2: 0,
		previous: 0,
		day: 0,
		data: null
	};
	
	var api = new mw.Api();

	function loadTemplate() {
		return api.ajax({
			action: 'parse',
			prop: 'text',
			title: conf.wgPageName,
			text: "{{Graph:PageViews|"+days+"|"+conf.wgPageName+"}}"
		});
	}
	
	function render() {
		mw.log('enter render');
		if ($('#statbox').length > 0) {
			return;
		}
		var nowMsg = 'pageview-now';
		var meanMsg = 'pageview-mean';
		var prevMsg = 'pageview-previous-same';
		if (stats.prev > stats.day) {
			prevMsg = 'pageview-previous-down';
		} else if (stats.prev < stats.day) {
			prevMsg = 'pageview-previous-up';
		}
		var $stat = $('<div>')
			.attr({'id': 'statbox', 'class': 'statbox mw-collapsible mw-collapsed',  'data-mw': 'interface'})
			.html(
				mw.message( 'pageview-help-short' ).parse()
				+ ' ' + mw.message( nowMsg, stats.day ).text()
				+ ' ' + mw.message( prevMsg, Math.abs(stats.day-stats.prev) ).text()
				+ ' ' + mw.message( meanMsg, Math.round(stats.mean), stats.count ).text())
			.append($('<div>').addClass('mw-collapsible-content'))
			.makeCollapsible()
			.insertAfter($('#bodyContent > .catlinks').last()); // the catlinks-id isn't unique
			//.insertAfter('#bodyContent > div.catlinks:last-of-type');
		//$stat.children('.mw-collapsible-toggle')
		loadTemplate()
			.done(function(data){
				var $collapsible = $stat.children('.mw-collapsible-content');
				$.each( data.parse.text, function ( index, text ) {
					$collapsible.append($('<div>').html(text));
				});
		});
	}
	
	var statsRequest = $.ajax({
		'cache':true,
		'dataType': 'json',
		'url': buildURI(ajax, {}) })
		.done(function(data){
			mw.log(data);
			if (!(data.items)) {
				data.items = [];
			}
			data.items.reverse();
			var num = 0;
			var meanAcc = 0;
			var sqrAcc = 0;
			$.each( data.items, function ( index, item ) {
				if (index!==0 && num < days) {
					meanAcc += item.views;
					sqrAcc += Math.pow(item.views, 2);
					num++;
				}
			});
			stats.data = data;
			stats.prev = data.items[1] !== undefined ? data.items[1].views : 0;
			stats.day = data.items[0] !== undefined ? data.items[0].views : 0;
			stats.count = num;
			stats.mean = meanAcc/num;
			stats.mean2 = meanAcc/days;
			stats.stdev = Math.sqrt((sqrAcc)/num - Math.pow(meanAcc/num, 2));
			stats.stdev2 = Math.sqrt((sqrAcc)/days - Math.pow(meanAcc/days, 2));
		});
	
	var msgs = {
		'pageview-now':'The page was shown {{PLURAL:$1|one time|$1 times}} last day,',
		'pageview-previous-down':'down {{PLURAL:$1|one pageview|$1 pageviews}} from previous day,',
		'pageview-previous-same':'same as previous day,',
		'pageview-previous-up':'up {{PLURAL:$1|one pageview|$1 pageviews}} from previous day,',
		'pageview-mean':'with a mean of {{PLURAL:$1|one pageview|$1 pageviews}} over {{PLURAL:$2|one day|$2 days}}.',
		'pageview-help-short':'[[m:Special:MyLanguage/Help:Pageviews|Pageviews]]:',
	};

	var amRequest = api.ajax({
		action: 'query',
		meta: 'allmessages',
		amlang: conf.wgUserLanguage,
		ammessages: Object.keys(msgs)
	})
	.done(function(data){
		$.each( data.query.allmessages, function ( index, message ) {
			if ( message.missing !== '' ) {
				mw.messages.set( message.normalizedname, message['*'] );
			} else if (msgs[message.name]) {
				mw.messages.set( message.normalizedname, msgs[message.name] );
			}
		});
	});
	mw.hook( 'wikipage.content' ).add(function( $content ) {
		Promise.all([amRequest, statsRequest]).then(render);
	});
});
});