User:Lupin/recentdiffs.js

//

// **************************************************

// Downloader

// **************************************************

window.Downloader=function(url) {

// Source: http://jibbering.com/2002/4/httprequest.html

this.http = false;

/*@cc_on @*/

/*@if (@_jscript_version >= 5)

// JScript gives us Conditional compilation,

// we can cope with old IE versions.

// and security blocked creation of the objects.

try {

this.http = new ActiveXObject("Msxml2.XMLHTTP");

} catch (e) {

try {

this.http = new ActiveXObject("Microsoft.XMLHTTP");

} catch (E) {

// this.http = false;

}

}

@end @*/

if (! this.http && typeof XMLHttpRequest!='undefined') this.http = new XMLHttpRequest();

this.url = url; this.id=null;

this.lastModified = null;

this.callbackFunction = null;

};

Downloader.prototype.send = function (x) {if (!this.http) return null; return this.http.send(x);};

Downloader.prototype.abort = function () {if (!this.http) return null; return this.http.abort();};

Downloader.prototype.runCallback = function () {this.callbackFunction(this);};

Downloader.prototype.getData = function () {if(!this.http) return null; return this.http.responseText;};

Downloader.prototype.setTarget = function () {if(!this.http) return null; this.http.open("GET", this.url, true);};

Downloader.prototype.start=function () {if(!this.http) return null; return this.http.send(null);};

Downloader.prototype.getReadyState=function () {if(!this.http) return null; return this.http.readyState;};

Downloader.prototype.getLastModifiedDate=function () {

if(!this.http) return null;

var lastmod=null;

try {

lastmod=this.http.getResponseHeader('Last-Modified');

} catch (err) {}

if (lastmod) return new Date(lastmod);

return null;

}

Downloader.prototype.setCallback = function (f) {

if(!this.http) return;

this.http.onreadystatechange = f;

this.callbackFunction = f;

};

Downloader.newDownload = function(url, id, callback) {

var d=new Downloader(url);

if (!d.http) return 'ohdear';

d.id=id;

d.setTarget();

var f = function () {

if (d.getReadyState() == 4) {

d.data=d.getData();

d.lastModified=d.getLastModifiedDate();

callback(d);

}

};

d.setCallback(f);

return d;//d.start();

};

Downloader.startDownload = function (url, id, callback, userData) {

var d=Downloader.newDownload(url, id, callback);

d.userData=userData;

if (typeof d == typeof '' ) return d;

return d.start();

};

// **************************************************

// DOM abbreviations

// **************************************************

$a = function (obj, parent) {

var p=(parent)?parent:document.body;

if (typeof obj== 'object' &&

obj.length != null && obj.length > 0 &&

typeof obj[0] == 'object' && obj[0].nodeType!=null) {

// assume it's a list of nodes

for (var i=0; i

p.appendChild(obj[i]);

}

} else p.appendChild(obj);

}

$e=function (id) {return document.getElementById(id);};

$c=function(elt) {return document.createElement(elt);},

$t=function(txt) {return document.createTextNode(txt);};

$ee=function(nm, parent) {var p=(parent)?parent:document; return p.getElementsByTagName(nm);};

// **************************************************

// Downloadqueue

// **************************************************

window.Downloadqueue=function(max) {

this.max=max || 5;

this.queue=[];

this.active={length: 0, highestIndex: 0};

this.timer=null;

this.freq=1000;

this.runFunction=Downloader.startDownload;

this.runQueueHook=function() {};

this.downloadCompleteHook=function() {};

}

Downloadqueue.prototype.push=function() {

this.queue.push(arguments);

}

Downloadqueue.prototype.runQueue=function () {

// document.title=['active:'+this.active.length, 'max:'+this.max, 'queuelen:'+this.queue.length].join('|');

this.runQueueHook();

if (this.active.length < this.max && this.queue.length > 0) {

var newActive=this.queue.shift();

var f=newActive[2];

var savedThis=this;

var idString=this.active.highestIndex++;

idString=idString.toString();

this.active[idString]=newActive;

++this.active.length;

// modify the third argument (the callback) so that it deletes the entry from this.active

// NB this is brittle - will break if the signature of this.runFunction changes

newActive[2] = function (d) {

f(d);

savedThis.active[idString]=null;

--savedThis.active.length;

savedThis.downloadCompleteHook();

};

this.activeId++;

this.runFunction.apply(window, newActive);

this.runQueue.apply(this, []); // run again to top up if needed

}

}

Downloadqueue.prototype.start=function () {

var savedThis=this;

this.timer=setInterval(function () { savedThis.runQueue.apply(savedThis) }, this.freq);

}

// **************************************************

// Recentchecker

// **************************************************

window.Recentchecker = function () {

this.status=$c('div'); var h1=$ee('h1')[0];

h1.parentNode.insertBefore(this.status, h1.nextSibling);

this.queue=new Downloadqueue(10);

this.numHits=0;

var savedThis=this;

this.queue.runQueueHook=function () {

var keys=[];

for (var k in savedThis.queue.active) {

if (savedThis.queue.active[k] && k != 'length' && k != 'highestIndex')

keys.push(k);

}

var s=[savedThis.numHits, ' diffs shown
',

savedThis.queue.active.length, ' active downloads, keys=[', keys.join(','), ']
',

savedThis.queue.queue.length, ' waiting'].join('');

savedThis.status.innerHTML=s;

}

this.queue.downloadCompleteHook=this.queue.runQueueHook;

this.queue.start();

}

Recentchecker.prototype.getDiffs=function () {

var ret=[];

for (var i=0; i

switch (document.links[i].innerHTML) {

case 'diff': case '(diff)':

case 'last':

ret.push(document.links[i]);

}

}

this.diffPages=ret;

}

Recentchecker.prototype.checkDiffs=function (re) {

if (this.diffPages==null) this.getDiffs();

for (var i=0; i

var savedThis=this;

var f=function(d) { savedThis.diffHandler.apply(savedThis, [d]); };

this.queue.push(this.diffPages[i].href, 0, f, {sourceNode: this.diffPages[i], regex: re});

}

}

Recentchecker.prototype.diffHandler=function (d) {

var data=d.data.replace(RegExp("^.*class='diff-context'.*$", 'gm'), '');

var diffTableMatch=/]*?class='diff'[^>]*?>(.|\n)*?<\/table>/.exec(data);

if (!diffTableMatch) return;

var diffTable=diffTableMatch[0];

var re=d.userData.regex;

var match = ( ! re || re.exec(diffTable));

if (! match) return;

this.numHits++;

var diffNode=d.userData.sourceNode;

var newDiv=$c('div'); newDiv.innerHTML='Match: ' + match[1] + '
' + match[0] + '
' + diffTable;

var nextBrSib=nextSiblingOfType(diffNode, 'br');

if (nextBrSib && nextBrSib.nextSibling) {

nextBrSib = nextBrSib.nextSibling;

diffNode.parentNode.insertBefore(newDiv, nextBrSib);

} else diffNode.parentNode.appendChild(newDiv);

}

// **************************************************

// Miscellany

// **************************************************

function isNodeName(node, str) {

return node.nodeName.toUpperCase() == str.toUpperCase();

}

function nextSiblingOfType(node, type) {

for (var n=node; n; n=n.nextSibling) {

if (isNodeName(n, type)) return n;

}

return null;

}

window.gettingBadWords=false;

window.badWords=null;

function getBadWords() {

window.gettingBadWords=true;

var d=

Downloader.startDownload(

'http://en.wikipedia.org/w/index.php?title=User:Lupin/badwords&action=raw&ctype=text/css',

0,

processBadWords);

}

function processBadWords(d) {

var data=d.data.split('\n');

var ret=[];

for (var i=0; i

var s=data[i];

if (s.length==0) continue;

if (s.charAt(0)=='<') continue;

ret.push(s.replace(RegExp('([-|.()\\+:!,?*^${}\\[\\]])', 'g'), '\\$1'));

}

window.badWords=RegExp(".*(([^.\s])\1\1|\\b(" + ret.join('|') + ")\\b).*", 'im');

}

function runOnce(f, time) {

var i=runOnce.timers.length;

var ff = function () { clearInterval(runOnce.timers[i]); f() };

var timer=setInterval(ff, time);

runOnce.timers.push(timer);

}

runOnce.timers=[];

runOnce.index=0;

function filteredRecentDiffs() {

if (! window.gettingBadWords) { getBadWords(); }

if (! window.badWords) { runOnce(filteredRecentDiffs, 500); return; }

new Recentchecker().checkDiffs(badWords);

}

function checkRecentDiffs() {

new Recentchecker().checkDiffs();

}

// **************************************************

// Installation

// **************************************************

function addlilink(tabs, url, name, id, title, key){

var na = document.createElement('a');

na.href = url;

na.appendChild(document.createTextNode(name));

var li = document.createElement('li');

if(id) li.id = id;

li.appendChild(na);

tabs.appendChild(li);

if(id)

{

if(key && title)

{

ta[id] = [key, title];

}

else if(key)

{

ta[id] = [key, ''];

}

else if(title)

{

ta[id] = ['', title];

}

}

// re-render the title and accesskeys from existing code in wikibits.js

akeytt();

return li;

}

function addToolboxLink(url, name, id){

var tb = document.getElementById('p-tb').getElementsByTagName('ul')[0];

addlilink(tb, url, name, id);

}

function addPowerdiffLink() {

addToolboxLink('#', 'Show filtered diffs', 'toolbox_filtereddiffs');

$e('toolbox_filtereddiffs').onclick=filteredRecentDiffs;

addToolboxLink('#', 'Show all diffs', 'toolbox_alldiffs');

$e('toolbox_alldiffs').onclick=checkRecentDiffs;

}

if (window.addEventListener) {

window.addEventListener("DOMContentLoaded",addPowerdiffLink,false) || window.addEventListener("load", addPowerdiffLink, false);

}

else if (window.attachEvent) {

window.attachEvent("onload",addPowerdiffLink);

}

else {

window._old_recent_onload = window.onload;

window.onload = function() {

window._old_recent_onload();

addPowerdiffLink();

}

}

//

/// Local Variables: ///

/// mode:c ///

/// fill-prefix:"// " ///

/// End: ///