User:ARTE/recentrevisionsbox.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.
////////////////////////////////////////////////////////////////////////////////

// This script reads the most recent revisions of a page using the MediaWiki API
// and places them in a box in the sidebar above the navigation box.
// The contents of the box become visible after pressing a button.
// For each revision, the edit time followed by the username is listed.
// The tooltip of the username link contains the edit summary.
// You can compare two revisions by successively clicking on their usernames.
// By clicking on the edit time, you can compare the selected revision with the
// previous one.
// In edit mode, any unsaved changes are not lost when the box is operated.
// Anyway, on some projects such as Meta, clicking the Show revisions button
// causes the page to be automatically saved and reloaded. I don't know how to
// work around this yet.
//
// Authors: nl:User:JePe, User:ARTE

function appendButton(divNodeId)
{
    var revContent = document.getElementById("recRevContent");
    var divNode = revContent.appendChild(document.createElement("div"));
    divNode.id = divNodeId;
    divNode.style.textAlign = "center";
    var button = divNode.appendChild(document.createElement("button"));
    button.onclick = loadJsonDoc;
    button.style.fontSize = "90%";
    button.style.marginTop = ".3em";
    button.style.padding = "0 .5em";
    return button;
}

function loadDiff(oldid,diffDir)
{
    var url = "/w/index.php?title=" + wgPageName;
    url += "&diff=" + diffDir;
    url += "&oldid=" + oldid;
    url += "&diffonly=1&action=render";
    if (window.XMLHttpRequest)
    { // native XMLHttpRequest
        diffReq = new XMLHttpRequest();
        diffReq.onreadystatechange = processDiff;
        diffReq.open("GET", url, true);
        diffReq.send(null);
    }
    else if (window.ActiveXObject)
    { // activeX version
       diffReq = new ActiveXObject("Microsoft.XMLHTTP");
       if (diffReq)
       {
          diffReq.onreadystatechange = processDiff;
          diffReq.open("GET", url, true);
          diffReq.send("");
       }
   }
}

function loadJsonDoc()
{
    var url = "/w/api.php?action=query&prop=revisions&format=json";
    url += "&pageids=" + wgArticleId + "&rvprop=timestamp|user|comment|ids";
    url += "&rvlimit=" + revCount;
    if (rvStartId != 0) url += "&rvstartid=" + rvStartId;
    if (window.XMLHttpRequest)
    { // native XMLHttpRequest
        apiReq = new XMLHttpRequest();
        apiReq.onreadystatechange = processReq;
        apiReq.open("GET", url, true);
        apiReq.send(null);
    }
    else if (window.ActiveXObject)
    { // activeX version
        apiReq = new ActiveXObject("Microsoft.XMLHTTP");
        if (apiReq)
        {
            apiReq.onreadystatechange = processReq;
            apiReq.open("GET", url, true);
            apiReq.send("");
        }
    }
}

function makeCloseButton(position)
{
    var closeButton = document.createElement("img");
    with (closeButton)
    {
        style.cssFloat = position;
        style.styleFloat = position;
        style.verticalAlign = "baseline";
        style.cursor = "pointer";
        title = closeButtonTitle;
        src =
            "http://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/" +
            "No-Symbol.svg/9px-No-Symbol.svg.png";
        height = "9";
        width = "9";
    }
    return closeButton;
}

function makeDateControl(date)
{
    return (
        date.getFullYear() * 10000 +
        (date.getMonth() + 1) * 100 +
        date.getDate()
        );
}

function makeRevisionLinkId(revisionId)
{
    return "rrb" + revisionId;
}

function nextRevisions()
{
    var button = appendButton("nextButton");
    button.innerHTML = buttonNextText;
    button.title = buttonNextTitle;
}

function processDiff()
{
    if (diffReq.readyState != 4) return;
    if (diffReq.status != 200) return;
    var bodyContent = document.getElementById("bodyContent");
    var diffFrame = document.createElement("div");
    diffFrame.id = "revisionsBoxDiff";
    diffFrame.innerHTML = diffReq.responseText;
    diffTable = diffFrame.getElementsByTagName("table")[0];
    if (!diffTable) return;
    if (diffTable.className != "diff") return;
    diffTable.style.border = "1px solid #ccc";
    diffTable.style.width = "100%";
    diffTable.style.paddingBottom = ".5em";
    diffTable.style.marginBottom = "1em";
    diffTable.style.marginTop = ".5em";
    var closeButton = makeCloseButton("left");
    closeButton.onclick = removeDiff;
    var tdNode = diffTable.getElementsByTagName("td");
    for (i=0; i < tdNode.length; i++)
    {
        if (tdNode[i].className == "diff-otitle")
        {
            tdNode[i].insertBefore(closeButton, tdNode[i].firstChild);
            tdNode[i].style.verticalAlign = "top";
        }
        else if (tdNode[i].className == "diff-ntitle")
            tdNode[i].style.verticalAlign = "top";
    }
    var diffFrameOld = document.getElementById("revisionsBoxDiff");
    if (diffFrameOld) diffFrameOld.parentNode.removeChild(diffFrameOld);
    bodyContent.parentNode.insertBefore(diffFrame,bodyContent);
    window.location.hash = "revisionsBoxDiff";
    var prevLink = document.getElementById("differences-prevlink");
    if (prevLink)
    {
        var oldid = prevLink.href.replace(/[\s\S]+&oldid=(\d+)[\s\S]*/, "$1");
        prevLink.href = "javascript:loadDiff(" + oldid + ", 'prev')";
    }
    var nextLink = document.getElementById("differences-nextlink");
    if (nextLink)
    {
        var oldid = nextLink.href.replace(/[\s\S]+&oldid=(\d+)[\s\S]*/, "$1");
        nextLink.href = "javascript:loadDiff(" + oldid + ", 'next')";
    }
}

function processReq()
{
    if (apiReq.readyState != 4) return;
    if (apiReq.status != 200) return;                              
    var jsonObj = eval("(" + apiReq.responseText + ")");  
    var revObj = jsonObj.query.pages[wgArticleId].revisions;  
    if (revObj) writeResults(revObj);  
    if (jsonObj["query-continue"])
    {
        rvStartId = jsonObj["query-continue"].revisions.rvstartid;
        nextRevisions();
    }
}

function recentRevisions()
{
    var revContent = document.getElementById("recRevContent");
    if (revContent)
    { // when pressed the close button
        prevRevisionId = undefined;
        revContent.innerHTML = "";
        rvStartId = 0;
        dateControl = 99999999;
    }
    else
    {
        var navigationBox = document.getElementById('p-navigation');
        var revBox = document.createElement("div");
        var revBox =
            navigationBox.parentNode.insertBefore(
            document.createElement("div"),
            navigationBox
            );
        revBox.id = "p-rev";
        revBox.className = "portlet";
        var h5Node = revBox.appendChild(document.createElement("h5"));
        h5Node.innerHTML = revBoxTitle;
        revContent = revBox.appendChild(document.createElement("div"));
        revContent.id = "recRevContent";
        revContent.className = "pBody";
        revContent.style.padding = "0 .3em .3em .3em";
        revContent.style.lineHeight = "1.2em";
        revContent.style.fontFamily = "Verdana, sans-serif";
    }
    var button = appendButton("showButton");
    button.innerHTML = buttonBeginText;
}

function removeDiff()
{
    var diffFrame = document.getElementById("revisionsBoxDiff");
    if (diffFrame) diffFrame.parentNode.removeChild(diffFrame);
}

function revisionClicked(revisionId)
{
    if (prevRevisionId == undefined)
    {
        var aNodeUser = document.getElementById(makeRevisionLinkId(revisionId));
        aNodeUser.style.color = "#f00";
        aNodeUser.style.textDecoration = "underline";
        prevRevisionId = revisionId;
    }
    else
    {
        var aNodeUser =
            document.getElementById(makeRevisionLinkId(prevRevisionId));
        aNodeUser.style.color = "";
        aNodeUser.style.textDecoration = "";
        if (prevRevisionId < revisionId)
            loadDiff(prevRevisionId, revisionId);
        else if (revisionId < prevRevisionId)
            loadDiff(revisionId, prevRevisionId);
        prevRevisionId = undefined;
    }
}

function writeResults(revObj)
{
    var showButton = document.getElementById('showButton');
    var nextButton = document.getElementById('nextButton');
    var revContent = document.getElementById("recRevContent");
    if (showButton)
    { 
        showButton.parentNode.removeChild(showButton);
        var closeButton = makeCloseButton("right");
        closeButton.onclick = recentRevisions;
        closeButton.style.marginTop = ".3em"; 
        revContent.appendChild(closeButton);
    }
    if (nextButton) nextButton.parentNode.removeChild(nextButton);
    var date = new Date();
    var dateNow = makeDateControl(date);
    for (i = 0; i < revObj.length; i++)
    {
        var rev = revObj[i];
        var time = rev.timestamp;
        var year = time.replace(/^(\d\d\d\d)[\s\S]+/, "$1");
        var month = time.replace(/^\d\d\d\d-(\d\d)[\s\S]+/, "$1");
        var day = time.replace(/^\d\d\d\d-\d\d-(\d\d)[\s\S]+/, "$1");
        var hours = time.replace(/[\s\S]+T(\d\d)[\s\S]+/, "$1");
        var minutes = time.replace(/[\s\S]+T\d\d:(\d\d)[\s\S]+/, "$1");
        date.setUTCFullYear(year, month - 1, day);
        date.setUTCHours(hours, minutes);
        var dateRevision = makeDateControl(date);
        if (dateRevision < dateControl)
        {
            var divNodeDate =
                revContent.appendChild(document.createElement("div"));
            divNodeDate.style.fontSize = "95%";
            divNodeDate.style.marginTop = ".3em";
            divNodeDate.style.fontWeight = "bold";
            divNodeDate.style.paddingLeft = ".5em";
            divNodeDate.innerHTML =
                date.getDate() + " " + monthName[date.getMonth()]; 
            if (dateNow - dateRevision > 10000)
                divNodeDate.innerHTML += " " + date.getFullYear();
            dateControl = dateRevision;   
        }   
        var divNode = revContent.appendChild(document.createElement("div"));
        divNode.style.marginLeft = "1em";
        divNode.style.textIndent = "-1em";
        divNode.style.fontSize = "95%";
        divNode.style.marginTop = ".3em";
        var aNodeTime = divNode.appendChild(document.createElement("a"));
        aNodeTime.innerHTML =
            (date.getHours() < 10) ? "0" + date.getHours() : date.getHours();
        aNodeTime.innerHTML += ":";
        aNodeTime.innerHTML +=
            (date.getMinutes() < 10) ?
            "0" + date.getMinutes() : date.getMinutes();
        aNodeTime.style.fontSize = "90%";
        aNodeTime.href = "javascript:loadDiff(" + rev.revid + ", 'prev')";
        aNodeTime.title = timeTitle;
        divNode.appendChild(document.createTextNode(" "));
        var aNodeUser = divNode.appendChild(document.createElement("a"));
        aNodeUser.id = makeRevisionLinkId(rev.revid);
        aNodeUser.innerHTML = rev.user;
        aNodeUser.title = rev.comment ? rev.comment.replace(/\\\//g, "/") : "";
        aNodeUser.href = "javascript:revisionClicked(" + rev.revid + ")";
    } 
}

var prevRevisionId;
var diffReq;
var apiReq;
var rvStartId = 0;
var revCount = 20; // max 50, higher numbers not possible, they give an error
var dateControl = 99999999; // must only be higher than today (yyyymmdd)
if (wgUserLanguage == "de")
{
    var timeTitle = "Unterschied zur vorherigen Version";
    var closeButtonTitle = "Schließen";
    var revBoxTitle = "Neuere Versionen";
    var buttonBeginText = "Versionen zeigen";
    var buttonNextText = "Folgende " + revCount;
    var buttonNextTitle = "Folgende " + revCount + " Versionen zeigen";
    var monthName = [
        "Januar", "Februar", "März", "April", "Mai", "Juni",
        "Juli", "August", "September", "Oktober", "November", "Dezember"
    ];
}
else if (wgUserLanguage == "it")
{
    var timeTitle = "Differenze dalla versione precedente";
    var closeButtonTitle = "Chiudi";
    var revBoxTitle = "versioni recenti"; 
    var buttonBeginText = "Mostra versioni";
    var buttonNextText = "Successive " + revCount;
    var buttonNextTitle = "Mostra le " + revCount + " versioni successive";
    var monthName = [
        "gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno",
        "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"
    ];
}
else if (wgUserLanguage == "nl")
{
    var timeTitle = "Verschillen met de vorige bewerking";
    var closeButtonTitle = "Sluiten";
    var revBoxTitle = "recente bewerkingen"; 
    var buttonBeginText = "Toon bewerkingen";
    var buttonNextText = "Volgende " + revCount;
    var buttonNextTitle = "Toon de volgende " + revCount + " bewerkingen";
    var monthName = [
        "januari", "februari", "maart", "april", "mei", "juni",
        "juli", "augustus", "september", "oktober", "november", "december"
    ];
}
else
{
    var timeTitle = "Differences with the previous revision";
    var closeButtonTitle = "Close";
    var revBoxTitle = "recent revisions"; 
    var buttonBeginText = "Show revisions";
    var buttonNextText = "Next " + revCount;
    var buttonNextTitle = "Show the next " + revCount + " revisions";
    var monthName = [
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December"
    ];
}
if (wgNamespaceNumber >= 0) addOnloadHook(recentRevisions);