Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// BetterHistory v0.6
// Copyright (c) 2005 by Colin Hill (colin@colinhill.us)
// This is 100% free code. Use it for anything.
 
// Arrays to hold revision info
oldids=new Array(100);
revisions=new Array(100);
 
var title="Error";
var offset=0;
 
// Object that will soon be the slider button
var handleImg;
 
// Diff status (determines which pages to request)
// 0  Current revision html
// 1  Diff w/ most recent revision
// 2  Diff w/ previous revision
// 3  Raw wikicode (doesn't work in Opera yet)
var diffStatus = 0;
 
/* Updates diff status */
function ChangeDiffStatus(newStatus)
{
	if(diffStatus != newStatus){
		diffStatus=newStatus;
		SetArticle(currentArticle);
	}
	else
		diffStatus=newStatus;
}
 
/* Returns an XMLHttpRequest object */
function CreateXMLHTTPObject(){
	var object=false;
 
	// Internet Explorer
	/*@cc_on @*/
	/*@if (@_jscript_version >= 5)
	try{
		object = new ActiveXObject("Msxml2.XMLHTTP");
	} catch(e){
		try{
			object = new ActiveXObject("Microsoft.XMLHTTP");
		} catch(e2){
			object = false;
		}
	}
	@end @*/
	// Other UAs
	if(!object && typeof XMLHttpRequest!='undefined'){
		object = new XMLHttpRequest();
	}
 
	return object;
}
 
function NullPage(){
	return '<br /><center>This is the end.<br /><br />'+
	       '<a href="http://en.wiki.x.io/wiki/Special:BetterHistory?article='+title+'&offset='+(offset-100)+'">Go forward 100 revisions.</a><br />'+
	       '<a href="http://en.wiki.x.io/wiki/Special:BetterHistory?article='+title+'&offset='+(offset-(-100))+'">Go back 100 revisions.</a>'+
	       '</center>';
}
 
/* Extract & format revision strings from history page */
function ExtractRevisions(string)
{
	// Extract revision strings
	var insideTagPair=false;
	var substring="";
	var currentRevision = 0;
	for(i=0; i<string.length; i++){
		// Start of tag pair?
		if(!insideTagPair){
			if((""+string.charAt(i)) == "<")
			if(string.substr(i, 4) == "<li>"){
				// Skip past the starting li tag
				i+=3; // strlen("<li>")
				insideTagPair=true;
				continue;
			}
		}
		// End of tag pair?
		else{
			// Check for ending tag
			if((""+string.charAt(i)) == "<")
			if(string.substr(i, 5) == "</li>"){
				// Append the extracted revision to the array
				revisions[currentRevision] = substring;
				currentRevision++;
 
				substring="";
				insideTagPair=false;
				continue;
			}
		}
 
		// Append current char?
		if(insideTagPair)
			substring+=string.charAt(i);
 
	}
 
	// Remove all the radio buttons from the strings
	for(x=0; x<100; x++){
		var blanking=false;
		var temp="";
 
		currentRevision=revisions[x]
		for(i=0; i<currentRevision.length; i++){
			// Not blanking?
			if(!blanking){
				// Start blanking?
				if(currentRevision.substr(i, 7) == "<input ")
					blanking=true;
				// Continue not blanking
				else
					temp+=currentRevision.charAt(i);
			}
			// Blanking
			else {
				// Check for ending tag
				if((""+currentRevision.charAt(i)) == "/")
				if((""+currentRevision.charAt(i+1)) == ">"){
					// Skip last char of the tag
					i++;
					// Stop blanking chars
					blanking=false;
				}
			}
		}
		revisions[x]=temp;
	}
 
	// Extract oldids, add to array
	var matches=null;
	var validRevision = new RegExp("oldid=([0-9]+)");
	for(i=0; i<100; i++)
		if(matches = validRevision.exec(revisions[i]))
			oldids[i]=matches[1];
}
 
/* Extracts articles from surrounding html */
function ExtractArticle(string)
{
	var firstChar = string.indexOf("<!-- start content -->");
	var lastChar = string.indexOf("<!-- end content -->");
	return string.substring(firstChar, lastChar);
}
 
var currentArticle;
 
/* Download & show an article */
function SetArticle(oldidIndex)
{
	currentArticle=oldidIndex;
 
	var xmlhttp = CreateXMLHTTPObject();
 
	document.getElementById("articleHTML").innerHTML="<br /><center><b>Loading...</b></center>";
 
	// Diff w/ most recent revision
	if(diffStatus == 1)
		xmlhttp.open("GET", "http://en.wiki.x.io/w/index.php?title="+title+"&diff=0&oldid="+oldids[oldidIndex], true);
	// Diff w/ previous revision
	else if((diffStatus == 2) && oldids[oldidIndex] && oldids[oldidIndex+1])
		xmlhttp.open("GET", "http://en.wiki.x.io/w/index.php?title="+title+"&diff="+oldids[oldidIndex]+"&oldid="+oldids[oldidIndex+1], true);
	// This revision's wikicode
	else if(diffStatus == 3)
		xmlhttp.open("GET", "http://en.wiki.x.io/w/index.php?title="+title+"&oldid="+oldids[oldidIndex]+"&action=raw", true);
	// Selected revision
	else
		xmlhttp.open("GET", "http://en.wiki.x.io/w/index.php?title="+title+"&oldid="+oldids[oldidIndex], true);
 
	// Function to handle results
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4){
			// Show raw if viewing wikicode
			if(diffStatus != 3)
				document.getElementById("articleHTML").innerHTML=ExtractArticle(xmlhttp.responseText);
			else
				document.getElementById("articleHTML").innerHTML="<pre>"+xmlhttp.responseText+"</pre>";
 
			// Page resizes when new article loads. Snap onto notch again.
			Snap(true);
		}
	}
 
	// Send request
	xmlhttp.send(null);
 
}
 
// Keeps track of the mouse button's status
var mousedown=false;
 
/* Returns the x coordinate of a specific notch */
function NotchCoord(notch){
	return 6*notch;
}
 
/* Returns the number of the nearest slider notch */
function NearestNotch(x){
	return Math.round(x/6.0);
}
 
// Current x pos on the track
currentX = NotchCoord(100);
 
/* Snaps slider button onto the nearest notch */
function Snap(butDontLoad){
	// Get X position of the track
	var object=document.getElementById("track");
	var trackPos = 0;
	while (object.offsetParent){
		trackPos += object.offsetLeft
		object = object.offsetParent;
	}
 
	// Snap to the nearest notch
	handleImg.style.left=""+(trackPos+NotchCoord(NearestNotch(currentX))-(12/2))+"px";
 
	// Update the currentX position
	currentX=NotchCoord(NearestNotch(currentX));
 
	// Null page
	if(NearestNotch(currentX) == 0)
		document.getElementById("articleHTML").innerHTML=NullPage();
	// Older revision
	else
		if(!butDontLoad) SetArticle(100-NearestNotch(currentX));
}
 
/* Moves the slider button to a new position */
function Slideto(x)
{
	// If the the mouse isn't dragging the button, return.
	if(!mousedown)
		return;
 
	// Get X position of the track
	var object=document.getElementById("track");
	var trackPos = 0;
	while (object.offsetParent){
		trackPos += object.offsetLeft
		object = object.offsetParent;
	}
 
	// Too far to the left?
	if(x<trackPos){
		currentX=0;
		handleImg.style.left=""+(trackPos-6)+"px"; //    on the mouse pointer
	}
	// Too far to the right?
	else if(x>(trackPos+600)){
		currentX=600;
		handleImg.style.left=""+(trackPos+600-6)+"px";
	}
	else{
		currentX=x-trackPos;
		handleImg.style.left=""+(x-7)+"px";
	}
 
	// Show the current revision string
	if(NearestNotch(currentX) != 0)
		document.getElementById('link').innerHTML = revisions[100-NearestNotch(currentX)];
	else
		document.getElementById('link').innerHTML = "Change offset?";
}
 
/* Handles all mouse movement */
function onmousemove_Handler(event){
 
	// Firefox
	if(event)
		Slideto(event.clientX);
 
	// Internet Explorer & Opera
	else
		Slideto(window.event.clientX);
}
document.onmousemove=onmousemove_Handler;
 
/* Handles mouseup events */
function onmouseup_Handler(){
	if(mousedown)
		Snap(false);
 
	mousedown=false;
}
document.onmouseup=onmouseup_Handler;
 
function onmousedown_Handler(e){
	var focusObject = !document.all ? e.target : event.srcElement;
	var topElement = !document.all ? "HTML" : "BODY";
 
	if (focusObject.id=="handleImg"){
		mousedown = true;
		return false;
	}
}
document.onmousedown=onmousedown_Handler;
 
/* Takes over the page if URL is for certain pages */
function CheckPage(){
	// Put a link on the normal history page
	var validHistoryURL = new RegExp(".+action=history.*");
	if(validHistoryURL.exec(location.href)){
		// What article?
		var matches;
		var titleExp = new RegExp("title=([^&]+)");
		if(matches = titleExp.exec(location.href))
			title = matches[1];
 
		// Offset?
		var matches;
		var offsetExp = new RegExp("offset=([^&]+)");
		if(matches = offsetExp.exec(location.href))
			offset = matches[1];
 
		document.getElementById("contentSub").innerHTML+='&nbsp;&nbsp;<a href="http://en.wiki.x.io/wiki/Special:BetterHistory?article='+title+'&offset='+offset+'">BetterHistory</a>';
	}
 
	validHistoryURL = new RegExp(".+Special:BetterHistory.*");
	if(validHistoryURL.exec(location.href)){
		// What article to request?
		var matches;
		var titleExp = new RegExp("article=([^&]+)");
		if(matches = titleExp.exec(location.href))
			title = matches[1];
 
		// Offset?
		var matches;
		var offsetExp = new RegExp("offset=([^&]+)");
		if(matches = offsetExp.exec(location.href))
			offset = matches[1];
 
		// Set window title
		document.title=title+" - BetterHistory - Wikipedia, the free encyclopedia"
		// Update weird little tab thingie
		document.getElementById("ca-article").innerHTML="<a href=\"\">BetterHistory</a>";
 
		document.getElementById("content").style.position="relative";
		document.getElementById("content").innerHTML =
 
// Start of new body content
 
'<!-- Options -->'+
'<center><table border="0" cellpadding="0" cellspacing="0" width="100%" height="30"><tr><td align="center">'+
 
'<form><input type="radio" name="diffStatus" checked onclick="ChangeDiffStatus(0);"/>This revision <input type="radio" name="diffStatus" onclick="ChangeDiffStatus(1);"/>Diff w/ most recent <input type="radio" name="diffStatus" onclick="ChangeDiffStatus(2);"/>Diff w/ previous <input type="radio" name="diffStatus" onclick="ChangeDiffStatus(3);"/>Raw wikicode</form>'+
 
'</td></tr></table></center>'+
 
'<!-- Header -->'+
'<center><table border="0" cellpadding="0" cellspacing="0" width="75%" height="40"><tr><td align="center"><span id="link">Downloading...</span></td></tr></table></center>'+
 
'<!-- Slider track -->'+
'<center><img id="track" src="http://gladstone.uoregon.edu/~chill1/betterhistory/slider_track.png"></center>'+
 
'<!-- Spacer image -->'+
'<div id="spacer" style="position:relative;"><br /></div>'+
 
'<!-- Article area -->'+
'<div id="articleHTML" style="position:relative;"></div>';
 
 
// End of body content
 
	}
 
	// Get X position of the track
	var object=document.getElementById("track");
	var xPos=0;
	var yPos=0;
	while (object.offsetParent){
		xPos += object.offsetLeft
		yPos += object.offsetTop
		object = object.offsetParent;
	}
 
	// Create the slider button
	handleImg=document.createElement('img');
 
	handleImg.style.position="absolute";
	handleImg.id="handleImg";
	handleImg.style.left=""+(594+xPos)+"px";
	handleImg.style.top=""+(6+yPos)+"px";
	handleImg.style.zIndex="10000";
	handleImg.setAttribute("src", "http://gladstone.uoregon.edu/~chill1/betterhistory/slider_button.gif");
 
	handleImg.ondragstart=function(){window.event.returnValue = false;}
 
	document.body.appendChild(handleImg);
 
	// Create XMLHttpRequest object
	var xmlhttp = CreateXMLHTTPObject();
 
	document.getElementById("articleHTML").innerHTML="<br /><center><b>Loading...</b></center>";
 
	// Make request for history page
	xmlhttp.open("GET", "http://en.wiki.x.io/w/index.php?title="+title+"&action=history&limit=100&offset="+offset);
 
	// Function to handle results
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4){
			ExtractRevisions(xmlhttp.responseText);
			document.getElementById('link').innerHTML = revisions[0];
 
			// Set article to current revision
			SetArticle(0);
		}
	}
 
	// Send request
	xmlhttp.send(null);
}
window.onload=CheckPage;