return function UnbinderCallback( match , a , b ) {
var current = self.prefix + self.counter + self.postfix;
self.history[current] = match;
++self.counter;
return current;
};
};  
function clone( obj, deep ) {
var objectClone = new obj.constructor;
for ( var property in obj )
if ( !deep ) {
objectClone[property] = obj[property];
}
else if ( typeof obj[property] == 'object' ) {
objectClone[property] = clone( obj[property], deep );
}
else {
objectClone[property] = obj[property];
}
return objectClone;
}  
namespaces = {
'-2': 'Media',
'-1': 'Special',
'0' : '',
'1' : 'Talk',
'2' : 'User',
'3' : 'User_talk',
'4' : 'Project',
'5' : 'Project talk',
'6' : 'Image',
'7' : 'Image talk',
'8' : 'MediaWiki',
'9' : 'MediaWiki talk',
'10': 'Template',
'11': 'Template talk',
'12': 'Help',
'13': 'Help talk',
'14': 'Category',
'15': 'Category talk',
'100': 'Portal',
'101': 'Portal talk'
};
function ln( ns, title ) {
var ns2ln = {
'0' : 'la',
'1' : 'lat',
'2' : 'lu',
'3' : 'lut',
'4' : 'lw',
'5' : 'lwt',
'6' : 'li',
'7' : 'lit',
'8' : 'lm',
'9' : 'lmt',
'10': 'lt',
'11': 'ltt',
'12': 'lh',
'13': 'lht',
'14': 'lc',
'15': 'lct',
'100': 'lp',
'101': 'lpt'
};
return "\{\{" + ns2ln[ns] + "|" + title + "\}\}";
}
Namespace = {
MAIN: 0,
TALK: 1,
USER: 2,
USER_TALK: 3,
PROJECT: 4,
PROJECT_TALK: 5,
IMAGE: 6,
IMAGE_TALK: 7,
MEDIAWIKI: 8,
MEDIAWIKI_TALK: 9,
TEMPLATE: 10,
TEMPLATE_TALK: 11,
HELP: 12,
HELP_TALK: 13,
CATEGORY: 14,
CATEGORY_TALK: 15,
PORTAL: 100,
PORTAL_TALK: 101,
MEDIA: -2,
SPECIAL: -1
};  
// Helper functions to change case of a string
String.prototype.toUpperCaseFirstChar = function {
return this.substr( 0, 1 ).toUpperCase + this.substr( 1 );
}  
String.prototype.toLowerCaseFirstChar = function {
return this.substr( 0, 1 ).toLowerCase + this.substr( 1 );
}  
String.prototype.toUpperCaseEachWord = function( delim ) {
delim = delim ? delim : ' ';
return this.split( delim ).map( function(v) { return v.toUpperCaseFirstChar } ).join( delim );
}  
String.prototype.toLowerCaseEachWord = function( delim ) {
delim = delim ? delim : ' ';
return this.split( delim ).map( function(v) { return v.toLowerCaseFirstChar } ).join( delim );
}  
/**
- Helper functions to get the month as a string instead of a number
- /  
Date.monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
Date.monthNamesAbbrev = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
];  
Date.prototype.getMonthName = function {
return Date.monthNames[ this.getMonth ];
}  
Date.prototype.getMonthNameAbbrev = function {
return Date.monthNamesAbbrev[ this.getMonth ];
}
Date.prototype.getUTCMonthName = function {
return Date.monthNames[ this.getUTCMonth ];
}  
Date.prototype.getUTCMonthNameAbbrev = function {
return Date.monthNamesAbbrev[ this.getUTCMonth ];
}  
// Accessor functions for wikiediting and api-access
Wikipedia = {};  
// we dump all XHR here so they won't loose props
Wikipedia.dump = [];  
Wikipedia.numberOfActionsLeft = 0;
Wikipedia.nbrOfCheckpointsLeft = 0;  
Wikipedia.actionCompleted = function( self ) {
if( --Wikipedia.numberOfActionsLeft <= 0 && Wikipedia.nbrOfCheckpointsLeft <= 0 ) {
Wikipedia.actionCompleted.event( self );
}
}  
// Change per action wanted
Wikipedia.actionCompleted.event = function {
new Status( Wikipedia.actionCompleted.notice, Wikipedia.actionCompleted.postfix, 'info' );
if( Wikipedia.actionCompleted.redirect != null ) {
// if it isn't an url, make it an relative to self (probably this is the case)
if( !/^\w+\:\/\//.test( Wikipedia.actionCompleted.redirect ) ) {
Wikipedia.actionCompleted.redirect = mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace( '$1', encodeURIComponent( Wikipedia.actionCompleted.redirect ).replace( /\%2F/g, '/' ) );
}
window.setTimeout( function { window.location = Wikipedia.actionCompleted.redirect } , Wikipedia.actionCompleted.timeOut );
}
}
wpActionCompletedTimeOut = typeof(wpActionCompletedTimeOut) == 'undefined' ? 5000 : wpActionCompletedTimeOut;
wpMaxLag = typeof(wpMaxLag) == 'undefined' ? 10 : wpMaxLag; // Maximum lag allowed, 5-10 is a good value, the higher value, the more agressive.  
Wikipedia.editCount = 10;
Wikipedia.actionCompleted.timeOut = wpActionCompletedTimeOut;
Wikipedia.actionCompleted.redirect = null;
Wikipedia.actionCompleted.notice = 'Action';
Wikipedia.actionCompleted.postfix = 'completed';  
Wikipedia.addCheckpoint = function {
++Wikipedia.nbrOfCheckpointsLeft;
}  
Wikipedia.removeCheckpoint = function {
if( --Wikipedia.nbrOfCheckpointsLeft <= 0 && Wikipedia.numberOfActionsLeft <= 0 ) {
Wikipedia.actionCompleted.event;
}
}  
/*
currentAction: text, the current action (required)
query: Object, the query (required)
oninit: function, the function to call when page gotten (required)
- /
Wikipedia.api = function( currentAction, query, oninit, statelem ) {
this.currentAction = currentAction;
this.query = query;
this.query['format'] = 'xml'; //LET THE FORCE BE WITH YOU!!!
this.oninit = oninit;
if( statelem ) {
statelem.status( currentAction )
} else {
this.statelem = new Status( currentAction );
}
++Wikipedia.numberOfActionsLeft;
}
Wikipedia.api.prototype = {
currentAction: '',
oninit: null,
query: null,
responseXML: null,
statelem: null,
counter: 0,
post: function {
var xmlhttp = sajax_init_object;
Wikipedia.dump.push( xmlhttp );
xmlhttp.obj = this;
xmlhttp.overrideMimeType('text/xml');
xmlhttp.open( 'POST' , mw.config.get('wgServer') + wgScriptPath + '/api.php', true);
xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xmlhttp.onerror = function {
var self = this.obj;
self.statelem.error( "Error " + this.target.status + " occurred while quering the api." );
}
xmlhttp.onload = function {
this.obj.responseXML = this.responseXML;
this.obj.oninit( this.obj );
Wikipedia.actionCompleted;
};
xmlhttp.send( QueryString.create( this.query ) );
}
}  
/*
currentAction: text, the current action (required)
query: Object, the query (required)
oninit: function, the function to call when page gotten (required)
onsuccess: function, a function to call when post succeeded
onerror: function, a function to call when we abort failed posts
onretry: function, a function to call when we try to retry a post
- /
Wikipedia.wiki = function( currentAction, query, oninit, onsuccess, onerror, onretry ) {
this.currentAction = currentAction;
this.query = query;
this.oninit = oninit;
this.onsuccess = onsuccess;
this.onerror = onerror;
this.onretry = onretry;
this.statelem = new Status( currentAction );
++Wikipedia.numberOfActionsLeft;
}  
Wikipedia.wiki.prototype = {
currentAction: '',
onsuccess: null,
onerror: null,
onretry: null,
oninit: null,
query: null,
postData: null,
responseXML: null,
statelem: null,
counter: 0,
post: function( data ) {
this.postData = data;
if( Wikipedia.editCount <= 0 ) {
this.query['maxlag'] = wpMaxLag; // are we a bot?
} else {
--Wikipedia.editCount;
}  
var xmlhttp = sajax_init_object;
Wikipedia.dump.push( xmlhttp );
xmlhttp.obj = this;
xmlhttp.overrideMimeType('text/xml');
xmlhttp.open( 'POST' , mw.config.get('wgServer') + wgScriptPath + '/index.php?' + QueryString.create( this.query ), true);
xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xmlhttp.onerror = function(e) {
var self = this.obj;
self.statelem.error( "Error " + e.target.status + " occurred while posting the document." );
}
xmlhttp.onload = function(e) {
var self = this.obj;
var status = e.target.status;
if( status != 200 ) {
if( status == 503 ) {
var retry = e.target.getResponseHeader( 'Retry-After' );
var lag = e.target.getResponseHeader( 'X-Database-Lag' );
if( lag ) {
self.statelem.warn( "current lag of " + lag + " seconds is more than our defined maximum lag of " + wpMaxLag + " seconds, will retry in " + retry + " seconds" );
window.setTimeout( function( self ) { self.post( self.postData ); }, retry * 1000, self );
return;
} else {