Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

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
 }
}