User:Cobaltcigs/HistoryGraph.js: Difference between revisions

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search
m (tweak)
(re-writ)
Line 1: Line 1:
  +
var wgPageName = mw.config.get('wgPageName');
function AddGraphLink() {
 
  +
var wgCurRevisionId = mw.config.get('wgCurRevisionId');
if(wgAction != "history") return;
 
  +
// var wgAction = mw.config.get('wgAction');
var div = document.getElementById("histlegend");
 
  +
var wgAction = new URLSearchParams(location.href).get("action"); // detect fake actions
if(div == null) return;
 
  +
var ul = div.getElementsByTagName("ul")[0];
 
  +
function HistoryGraph() {
if(ul == null) return;
 
  +
if(wgCurRevisionId == 0) return;
ul.innerHTML += '<li><a onclick="ShowGraph()">Show graph</a></li>';
 
  +
var hist = document.getElementById("ca-history");
}
 
  +
if(!hist) return;
function HideGraph() {
 
var old = document.getElementById("history-graph");
+
var li = document.createElement('li');
  +
var a = document.createElement('a');
if(old) old.style.visibility = "hidden";
 
  +
li.id = 'ca-graph';
}
 
  +
a.href = `/w/index.php?title=${wgPageName}&action=graph`;
function ShowGraph() {
 
  +
a.title = "View graph of page history";
var old = document.getElementById("history-graph");
 
  +
a.innerText = "Graph";
if(old) {
 
  +
li.appendChild(a);
old.style.visibility = "visible";
 
  +
hist.insertAdjacentElement("afterend", li);
return;
 
  +
if(wgAction != "graph") return;
}
 
  +
var contentDiv = document.getElementById("mw-content-text");
var width = 640, height = 480, color = "red", stroke_width = 2;
 
  +
contentDiv.innerHTML = '';
var b = [];
 
  +
var fakeTitle = wgPageName.replace(/_/g, " ") + ": History graph";
var e = document.getElementsByClassName("history-size");
 
  +
document.getElementById("firstHeading").innerHTML = fakeTitle;
if(e.length == 0) return;
 
  +
document.title = fakeTitle;
for(var i = 0; i < e.length; i++) {
 
  +
var v = parseInt(e[i].innerText.replace(/\D/g, ""));
 
  +
var ym = new Date().toJSON().match(/^(\d+)\-(\d+)/);
if(isNaN(v)) continue;
 
  +
var yyyy = parseInt(ym[1]), mm = parseInt(ym[2]), d1 = "01T00:00:00Z";
b.push(v);
 
  +
var f = function(d) { return d.toString().padStart(2,'0'); }
  +
var url_base_dbg = '/w/api.php?action=query&prop=revisions&rvlimit=1&rvprop=size|timestamp|ids';
  +
var url_base = '/w/api.php?action=query&prop=revisions&rvlimit=1&rvprop=size&format=json';
  +
var f1 = function(r1) { return r1.json(); };
  +
var sz = [];
  +
var doneLoading = function() {
  +
var divs = contentDiv.getElementsByTagName("div");
  +
divs[divs.length-1].innerHTML += " (No more found!)";
  +
sz.push(0);
  +
drawGraph();
 
}
 
}
  +
var loop = function() {
if(b.length == 1) b.push(b[0]); // flat line for single rev
 
  +
var time = [f(yyyy), f(mm), d1].join('-');
b.reverse();
 
  +
var url_i = `&titles=${wgPageName}&rvstart=${time}`;
var max = Math.max.apply(null, b), min = Math.min.apply(null, b);
 
var dx = width/(b.length - 1);
+
var url = url_base + url_i;
var db = max-min;
+
var dbg_url = url_base_dbg + url_i;
  +
contentDiv.innerHTML += `<div><a href="${dbg_url}">Fetching last edit before ${time}...</a></div>`;
var dy = height/db;
 
var om = Math.floor(Math.log10(db)-0.5);
+
var f2 = function(r2) {
var dd = Math.pow(10, om);
+
var jtxt = JSON.stringify(r2.query);
var da = Math.ceil(min/dd)*dd;
+
var ms = jtxt.match(/"size"\:(\d+)/);
  +
if(!ms) { doneLoading(); return; }
var db = Math.floor(max/dd)*dd;
 
  +
sz.push(parseInt(ms[1]));
var pts = [];
 
  +
mm--;
for(var i = 0; i < b.length; i++)
 
  +
if(mm==0) { mm = 12; yyyy--; }
pts.push(`${(i * dx)}, ${height - (b[i]-min) * dy}`);
 
  +
loop();
var gpath = [], gtext = [];
 
  +
};
for(var i = da; i <= db; i += dd) {
 
  +
fetch(url).then(f1).then(f2);
var y = height - (i - min) * dy;
 
  +
};
gpath.push(`<path d="M0,${y} L${width},${y}" />`);
 
  +
loop();
gtext.push(`<text x="40" y="${y}">${i}</text>`);
 
  +
var drawGraph = function() {
  +
var height = 480, color = "red", stroke_width = 2;
  +
var q = "JFMAMJJASOND";
  +
sz.reverse();
  +
var max = Math.max.apply(null, sz);
  +
var dl = Math.pow(10, Math.floor(Math.log10(max)-0.5));
  +
var dx = 20;
  +
var dy = height/max;
  +
var lmax = Math.floor(max/dl)*dl;
  +
var width = dx * (sz.length + 1);
  +
var pts = [];
  +
var vpath=[], vtext = [], ytext = [];
  +
for(var i = 0; i < sz.length; i++) {
  +
pts.push(`${(i * dx)}, ${height - (sz[i] * dy)}`);
  +
var x = i * dx;
  +
var h = (mm==1)? (height+40) : height;
  +
vpath.push(`<path d="M${x},0 L${x},${h}" />`);
  +
vtext.push(`<text x="${x}" y="${height+20}">${q[mm-1]}</text>`);
  +
if(i == 0 || mm == 1)
  +
ytext.push(`<text x="${x}" y="${height+40}">${yyyy}</text>`);
  +
mm++;
  +
if(mm > 12) { mm = 1; yyyy++; }
  +
}
  +
var hpath = [], htext = [];
  +
for(var i = 0; i <= lmax; i += dl) {
  +
var y = height - (i * dy);
  +
hpath.push(`<path d="M0,${y} L${width},${y}" />`);
  +
htext.push(`<text x="40" y="${y}">${i}</text>`);
  +
}
  +
var path = `<path d="M${pts.join(' L')}" stroke="${color}" stroke-width="${stroke_width}" fill="none" />`;
  +
var g1 = `<g stroke="gray" stroke-width="1" fill="none">${hpath.join('')}${vpath.join('')}</g>`;
  +
var g2 = `<g font-family="monospace" font-size="12px" text-align="right" color="black">${htext.join('')}${vtext.join('')}${ytext.join('')}</g>`;
  +
var svg = `<svg style="width:${width}px; height:${height+60}px;">${g1}${path}${g2}</svg>`;
  +
contentDiv.innerHTML = svg;
 
}
 
}
var path = `<path d="M${pts.join(' L')}" stroke="${color}" stroke-width="${stroke_width}" fill="none" />`;
 
var g1 = `<g stroke="gray" stroke-width="1" fill="none">${gpath.join('')}</g>`;
 
var g2 = `<g font-family="monospace" font-size="12px" text-align="right" color="black">${gtext.join('')}</g>`;
 
var svg = `<svg style="width:${width}px; height:${height}px;">${g1}${path}${g2}</svg>`;
 
var divStyle = `position:fixed; top:50%; left:50%; transform:translate(-50%, -50%); display:inline-block; border: 1px solid black; background-color:white;`;
 
var xbox = `<button style="float:right; height: 25px; width: 25px; font-size:20px; line-height:100%; font-weight: bolder; background-color:red; color:white;" onclick="HideGraph()">×</button>`;
 
var div = `<div id="history-graph" style="${divStyle}">${xbox}${svg}</div>`;
 
document.body.innerHTML += div;
 
 
}
 
}
  +
  +
HistoryGraph();

Revision as of 10:16, 16 October 2019

var wgPageName = mw.config.get('wgPageName');
var wgCurRevisionId = mw.config.get('wgCurRevisionId');
// var wgAction = mw.config.get('wgAction');
var wgAction = new URLSearchParams(location.href).get("action"); // detect fake actions

function HistoryGraph() {
	if(wgCurRevisionId == 0) return;
	var hist = document.getElementById("ca-history");
	if(!hist) return;
	var li = document.createElement('li');
	var a = document.createElement('a');
	li.id = 'ca-graph';
	a.href = `/w/index.php?title=${wgPageName}&action=graph`;
	a.title = "View graph of page history";
	a.innerText = "Graph";
	li.appendChild(a);
	hist.insertAdjacentElement("afterend", li);
	if(wgAction != "graph") return;
	var contentDiv = document.getElementById("mw-content-text");
	contentDiv.innerHTML = '';
	var fakeTitle = wgPageName.replace(/_/g, " ") + ": History graph";
	document.getElementById("firstHeading").innerHTML = fakeTitle;
	document.title = fakeTitle;
	
	var ym = new Date().toJSON().match(/^(\d+)\-(\d+)/);
	var yyyy = parseInt(ym[1]), mm = parseInt(ym[2]), d1 = "01T00:00:00Z";
	var f = function(d) { return d.toString().padStart(2,'0'); }
	var url_base_dbg = '/w/api.php?action=query&prop=revisions&rvlimit=1&rvprop=size|timestamp|ids';
	var url_base = '/w/api.php?action=query&prop=revisions&rvlimit=1&rvprop=size&format=json';
	var f1 = function(r1) { return r1.json(); };
	var sz = [];
	var doneLoading = function() {
		var divs = contentDiv.getElementsByTagName("div");
		divs[divs.length-1].innerHTML += " (No more found!)";
		sz.push(0);
		drawGraph();
		}
	var loop = function() {
		var time = [f(yyyy), f(mm), d1].join('-');
		var url_i = `&titles=${wgPageName}&rvstart=${time}`;
		var url = url_base + url_i;
		var dbg_url = url_base_dbg + url_i;
		contentDiv.innerHTML += `<div><a href="${dbg_url}">Fetching last edit before ${time}...</a></div>`;
		var f2 = function(r2) {
			var jtxt = JSON.stringify(r2.query);
			var ms = jtxt.match(/"size"\:(\d+)/);
			if(!ms) { doneLoading(); return; }
			sz.push(parseInt(ms[1]));
			mm--;
			if(mm==0) { mm = 12; yyyy--; }
			loop();
			};
		fetch(url).then(f1).then(f2);
		};
	loop();
	var drawGraph = function() {
		var height = 480, color = "red", stroke_width = 2;
		var q = "JFMAMJJASOND";
		sz.reverse();
		var max = Math.max.apply(null, sz);
		var dl = Math.pow(10, Math.floor(Math.log10(max)-0.5));
		var dx = 20;
		var dy = height/max;
		var lmax = Math.floor(max/dl)*dl;
		var width = dx * (sz.length + 1);
		var pts = [];
		var vpath=[], vtext = [], ytext = [];
		for(var i = 0; i < sz.length; i++) {
			pts.push(`${(i * dx)}, ${height - (sz[i] * dy)}`);
			var x = i * dx;
			var h = (mm==1)? (height+40) : height;
			vpath.push(`<path d="M${x},0 L${x},${h}" />`);
			vtext.push(`<text x="${x}" y="${height+20}">${q[mm-1]}</text>`);
			if(i == 0 || mm == 1) 
				ytext.push(`<text x="${x}" y="${height+40}">${yyyy}</text>`);
			mm++;
			if(mm > 12) { mm = 1; yyyy++; }
			}
		var hpath = [], htext = [];
		for(var i = 0; i <= lmax; i += dl) {
			var y = height - (i * dy);
			hpath.push(`<path d="M0,${y} L${width},${y}" />`);
			htext.push(`<text x="40" y="${y}">${i}</text>`);
			}
		var path = `<path d="M${pts.join(' L')}" stroke="${color}" stroke-width="${stroke_width}" fill="none" />`;
		var g1 = `<g stroke="gray" stroke-width="1" fill="none">${hpath.join('')}${vpath.join('')}</g>`;
		var g2 = `<g font-family="monospace" font-size="12px" text-align="right" color="black">${htext.join('')}${vtext.join('')}${ytext.join('')}</g>`;
		var svg = `<svg style="width:${width}px; height:${height+60}px;">${g1}${path}${g2}</svg>`;
		contentDiv.innerHTML = svg;
		}
	}

HistoryGraph();