Jump to content

Wikipedia:WikiProject User scripts/Scripts/TimeTraveller.js

From Wikipedia, the free encyclopedia
/* Timetravel, version [0.2.0]
Documentation: Wikipedia:WikiProject User scripts/Scripts/TimeTraveller

Notes:
* Does not take into account:
** Old versions of templates, images
** Moved page titles
** Renamed users
** Time-sensitive magic words
*/

//to be localised
tt_currentrevision = 'Current revision';
tt_history='History';

//
// this code deals with the first access to an old page
// We have the revision id, but not the timetravel timestamp --> need to find it and set tt_timetravel
//
if(queryString('oldid') && !queryString('timetravel') && !queryString('diff') && mw.config.get('wgAction') == 'view')  addOnloadHook(addTimetravelButton)
function addTimetravelButton() {
 var url = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?maxage=300&smaxage=300&action=query&prop=revisions&rvprop=timestamp|ids&format=json&callback=addTimetravelCB&revids=' + queryString('oldid');
 mw.loader.load(url);
}

var tt_timetravel=false;
function addTimetravelCB(obj) {
 if(!obj['query'] || !obj['query']['pages'] || !obj['query']['pages'][mw.config.get('wgArticleId')]) return
 var rev = obj['query']['pages'][mw.config.get('wgArticleId')]['revisions'];
 var ts ='';
 for(var i in rev) {
   if(rev[i]['revid'] == queryString('oldid')) {
     ts = rev[i]['timestamp'];
   }
 }
 tt_timetravel=ts;
 engageTimetravelLinks();
}

//
// this code deals with the old pages accessed from another old one
// We thus have the tt_timetravel parameter
//
if(queryString('timetravel') && mw.config.get('wgAction') == 'view') addOnloadHook(engageTimetravelLinks)

// this is the routine called by the 2 previous cases

function engageTimetravelLinks() {
 if(!tt_timetravel) tt_timetravel=queryString('timetravel');
 appendCSS('a.timetravel { color:#00ff00 !important;} a.ttused {color:#ff0000 !important;}');

 engageTT2 (document.getElementById('bodyContent') || document.getElementById('content') || document.body, "A");
 engageTT2 (document.getElementById('p-cactions'), "B");
}

function engageTT2 (docobj, tag) {
 if (!docobj) return;
 var a = docobj.getElementsByTagName('a');

 for(var i=0;i<a.length;i++) {
   if (tag=='B' && a[i].innerHTML==tt_history) {
      a[i].href=a[i].href + '&offset=' + tt_timetravel.replace(/[^0-9]/g,"");
      continue
   }
   // Exclude: catlinks, extiw/external/new/image, diff/oldid/action, special, http/uri, media?, anchors?, imagemap?
   if(a[i].className.search(/(extiw|external|new|image)/ig) != -1) continue
   if(a[i].href.search(/(\/wiki\/(Category\:|Special\:)|diff\=|oldid\=|action\=|Special\:Cite)/ig) != -1) continue
   if(a[i].innerHTML==tt_currentrevision) continue;

   var link = a[i].href;
   link = link.replace(mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace(/\$1/,''),'');
   if(link.indexOf('#') != -1) link = link.substr(0,link.indexOf('#'));
   if(link.search(/(http|https|file|javascript)\:/ig) == 0) continue

   a[i].onmouseover=timetravel;
//    a[i].className += ' timetravel';
   a[i].id = 'ttlink-' + tag + i;
 }
}

//
// this code deals with the mouseOver an anchor
//
var tt_anchor, tt_id; // this may create a problem if several mouseover are fired before they can be fully handled
function timetravel(e) {
 //first, let's find the anchor
 var targ;
 if (!e) var e = window.event;
 if (e.target) targ = e.target;
 else if (e.srcElement) targ = e.srcElement;
 if (targ.nodeType == 3) // defeat Safari bug
    targ = targ.parentNode;
 var a = targ;
 var link = a.href;

 // no need to do anything else if it already has timetravel
 if (link.indexOf('timetravel=') != -1) {
   return
 }

 // block the href until updated
 a.className += ' ttused';
 if (link.indexOf('javascript:void("') !=-1) { // this happens when the call back does not happen! Remove it.
   link=link.substr( ('javascript:void("').length, link.length- ('javascript:void("').length- ('");').length);
 } else {
   a.href = 'javascript:void("' + a.href + '");';
 }

 //set the global variables
 link = link.replace(mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace(/\$1/,''),'');
 link = link.replace (/_/g, ' ');
 if(link.indexOf('#') != -1) {
      tt_anchor=link.substr(link.indexOf('#'))
      link = link.substr(0,link.indexOf('#')); 
 } else {tt_anchor=''};
 tt_id=a.id;

 //call the API
 var url = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?maxage=300&smaxage=300&action=query&prop=revisions&&rvprop=ids&rvlimit=1&rvstart=' + tt_timetravel + '&format=json&callback=timetravelCB&titles=' + encodeURIComponent(decodeURIComponent(link));
 url+= '&rnd=' + Math.random() // add a random element to make sure it is called
 mw.loader.load(url);
}

function timetravelCB(obj) {
 var a = document.getElementById(tt_id);

 if(!obj['query'] || !obj['query']['pages']) return
 var pages = obj['query']['pages'];
 var rev;
 var title = '';
 for(var i in pages) {
   rev = pages[i]['revisions'];
   title = pages[i]['title'];
 }
 if(!rev) {
   //unblock the link
   url=a.href.substr( ('javascript:void("').length, a.href.length- ('javascript:void("').length- ('");').length);
   a.href=url;
   a.className ='';
//    alert('No such page, or no revisions found that old.\n');
 } else {
   a.onmouseover=''; // no need to fire this anymore
   var id = 0;
   for(var i in rev) {
     id = rev[i]['revid'];
   }
   if(id != 0) {
     var url = mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=' + encodeURIComponent(title) + '&oldid=' + id + '&timetravel=' + tt_timetravel +tt_anchor ;
     a.href = url;
     a.className ='';
   }
 }
}

function queryString(p) {
 var re = RegExp('[&?#]' + p + '=([^&#]*)');
 var matches;
 if (matches = re.exec(document.location)) {
   try { 
     return decodeURI(matches[1]);
   } catch (e) {
   }
 }
 return null; 
}

//
// Add links to timestamps in talk pages
//

 if (mw.config.get('wgAction') == 'view')  addOnloadHook(addDateLinks);

 function addDateLinks() {
    var newContent = document.getElementById('bodyContent');
    if (! newContent || ! newContent.innerHTML || newContent.innerHTML=='') return;
    newContent=newContent.innerHTML;

    var tt_regDate= /(\d?\d):(\d\d), (\d?\d) (January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d\d\d\d) \(UTC\)/g;
    var dates= newContent.match(tt_regDate);
    if (!dates || ! dates.length) return;
    for (var j=0;j<dates.length;j++) {
       tt_regDate.lastIndex=0;
       var a = tt_regDate.exec(dates[j]);
       if (!a) continue;
       var dateLink=a[5] +'-'+ tt_2(a[4]) +'-'+ tt_2(a[3]) +'T'+ tt_2(a[1]) +':'+ tt_2(a[2]) + ':59Z';
       dateLink="<a href=javascript:void('" + dateLink +"') id='" + dateLink +"' onmouseover='getURLofThisPageFor("+ '"'+dateLink+'"'+ ")'>"+ dates[j]+ "</a>";

       var r= dates[j].replace("(","\\(");
       r = r.replace(")","\\)");
       r = new RegExp(r, "g");
       newContent=newContent.replace(r, dateLink);
    }
   document.getElementById('bodyContent').innerHTML=newContent
 };
 
//
// this code deals with the mouseOver an anchor
//
var tt_tentativeDate; 
function getURLofThisPageFor(aDate) {
     //first, let's find the anchor
     var a=document.getElementById(aDate);
     if (!a) return;

     // no need to do anything else if it already has timetravel
     if (a.href.indexOf('timetravel=') != -1) return;

    //set the global variables
    tt_tentativeDate=aDate;

    //call the API
    var pageName= mw.config.get('wgPageName').replace (/()\/Archive_[\d]*/,'$1');

    var url = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?maxage=300&smaxage=300&action=query&prop=revisions&&rvprop=ids&rvlimit=1&rvstart=' + aDate + '&format=json&callback=getURLofThisPageCB&titles=' + encodeURIComponent(decodeURIComponent(pageName));
    url+= '&rnd=' + Math.random() // add a random element to make sure it is called
    mw.loader.load(url);
};

function getURLofThisPageCB (obj) {
    if (!tt_tentativeDate) return;
    var a = document.getElementById(tt_tentativeDate);
    if (!a) return;

    if(!obj['query'] || !obj['query']['pages']) return
    var pages = obj['query']['pages'];
    var rev;
    var title='';
    for (var i in pages) {
      rev = pages[i]['revisions'];
      title = pages[i]['title'];
    };
    if(!rev) {
      //unblock the link
      url=a.href.substr( ('javascript:void("').length, a.href.length- ('javascript:void("').length- ('");').length);
      a.href=url;
      a.className ='';
   //    alert('No such page, or no revisions found that old.\n');
    } else {
      a.onmouseover=''; // no need to fire this anymore
      var id = 0;
      for (var i=0;i<rev.length;i++)  {
        id = rev[i]['revid'];
      };
      title=title.replace (/()\/Archive_[\d]*/,'$1');
      if(id != 0) {
        var url = mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=' + encodeURIComponent(title) + '&oldid=' + id + '&timetravel=' + tt_tentativeDate ;
        a.href = url;
        a.className ='';
      }
    }
};

function tt_2 (s) {
 switch (s) {
   case '1': return '01';
   case '2': return '02';
   case '3': return '03';
   case '4': return '04';
   case '5': return '05';
   case '6': return '06';
   case '7': return '07';
   case '8': return '08';
   case '9': return '09';
   case 'January': return '01';
   case 'February': return '02';
   case 'March': return '03';
   case 'April': return '04';
   case 'May': return '05';
   case 'June': return '06';
   case 'July': return '07';
   case 'August': return '08';
   case 'September': return '09';
   case 'October': return '10';
   case 'November': return '11';
   case 'December': return '12';
   case 'Jan': return '01';
   case 'Feb': return '02';
   case 'Mar': return '03';
   case 'Apr': return '04';
   case 'May': return '05';
   case 'Jun': return '06';
   case 'Jul': return '07';
   case 'Aug': return '08';
   case 'Sep': return '09';
   case 'Oct': return '10';
   case 'Nov': return '11';
   case 'Dec': return '12';
   default: return s
 }
}