User:Beetstra/morebits.js

/** RegExp.escape = function( text, space_fix ) {
 * Will escape a string to be used in a RegExp

if ( !arguments.callee.sRE ) { arguments.callee.sRE = /(\/|\.|\*|\+|\?|\||\(|\)|\[|\]|\{|\}|\\|\$|\^)/g; }

text = text.replace( arguments.callee.sRE, '\\$1' );

// Special Mediawiki escape, underscore/space is the same, often at lest:

if( space_fix ) { text = text.replace( / |_/g, '[_ ]' ); }

return text;

} 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' }; /**
 * 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 ]; }

// Simple helper functions to see what groups a user might belong

function userIsInGroup( group ) { if( !Array.indexOf ) { Array.prototype.indexOf = function( needle ) { for( var i in this ) { if( this[i] == needle ) { return i;             } }         return -1; } }  if( !Array.lastIndexOf ) { Array.prototype.lastIndexOf = function( needle ) { for( var i = this.length; i >= 0; --i ) { if( this[i] == needle ) { return i;             } }         return -1; } } }

function userIsAnon { return wgUserGroups == null; }

// AOL Proxy IP Addresses (2007-02-03) var AOLNetworks = [ '64.12.96.0/19',	'149.174.160.0/20',	'152.163.240.0/21',	'152.163.248.0/22',	'152.163.252.0/23',	'152.163.96.0/22',	'152.163.100.0/23',	'195.93.32.0/22',	'195.93.48.0/22',	'195.93.64.0/19',	'195.93.96.0/19',	'195.93.16.0/20',	'198.81.0.0/22',	'198.81.16.0/20',	'198.81.8.0/23',	'202.67.64.128/25',	'205.188.192.0/20',	'205.188.208.0/23',	'205.188.112.0/20',	'205.188.146.144/30',	'207.200.112.0/21', ];

// AOL Client IP Addresses (2007-02-03) var AOLClients = [ '172.128.0.0/10',	'172.192.0.0/12',	'172.208.0.0/14',	'202.67.66.0/23',	'172.200.0.0/15',	'172.202.0.0/15',	'172.212.0.0/14',	'172.216.0.0/16',	'202.67.68.0/22',	'202.67.72.0/21',	'202.67.80.0/20',	'202.67.96.0/19', ];

/**
 * ipadress is in the format 1.2.3.4 and network is in the format 1.2.3.4/5

function isInNetwork( ipaddress, network ) { var iparr = ipaddress.split('.'); var ip = (parseInt(iparr[0]) << 24) + (parseInt(iparr[1]) << 16) + (parseInt(iparr[2]) << 8) + (parseInt(iparr[3]));

var netmask = 0xffffffff << network.split('/')[1];

var netarr = network.split('/')[0].split('.'); var net = (parseInt(netarr[0]) << 24) + (parseInt(netarr[1]) << 16) + (parseInt(netarr[2]) << 8) + (parseInt(netarr[3]));

return (ip & netmask) == net; }

/* Returns true if given string contains a valid IP-address, that is, from 0.0.0.0 to 255.255.255.255*/ function isIPAddress( string ){ var res = /(\d{1,4})\.(\d{1,3})\.(\d{1,3})\.(\d{1,4})/.exec( string ); return res != null && res.slice( 1, 5 ).every( function( e ) { return e < 256; } ); }

/**
 * Maps the querystring to an object
 * Functions:
 * QueryString.exists(key)
 * returns true if the particular key is set
 * QueryString.get(key)
 * returns the value associated to the key
 * QueryString.equals(key, value)
 * returns true if the value associated with given key equals given value
 * QueryString.toString
 * returns the query string as a string
 * Optional parameter to exists, get and equals, can define another query string, but remember that that string wont be cached.
 * returns the query string as a string
 * Optional parameter to exists, get and equals, can define another query string, but remember that that string wont be cached.
 * Optional parameter to exists, get and equals, can define another query string, but remember that that string wont be cached.

function QueryString {}

QueryString.init = function(str) { var params = {};

if( QueryString.params != null && !str ) { return; }	if ( !str ) { QueryString.params = {}; }	var queryString = str || location.search.substring(1);

if(queryString.length == 0) { return; }

if( !str ) { QueryString.str = queryString; }

queryString.replace(/\+/, ' ');

var args = queryString.split('&');

for( var i in args ) { var pair = args[i].split( '=' ); var key = decodeURIComponent( pair[0] ), value = key;

if( pair.length == 2 ) { value = decodeURIComponent( pair[1] ); }

params[key] = value; }

if( !str ) { QueryString.params = params; }

return params; }

QueryString.get = function(key, str) { if( str ) { var val = QueryString.init(str)[key]; return val ? val : null; } else if( QueryString.params == null ) { QueryString.init; }	return QueryString.params[key] ? QueryString.params[key] : null; };

QueryString.exists = function(key, str) { if( str ) { return QueryString.init(str)[key] ? true : false; } else if( QueryString.params == null ) { QueryString.init; }

return QueryString.params[key] ? true : false; }

QueryString.equals = function(key, value, str) { if (str ) { return QueryString.init(str)[key] == value ? true : false; } else if( QueryString.params == null ) { QueryString.init; }	return QueryString.params[key] == value ? true : false; }

QueryString.toString = function { if( QueryString.str == null ) { QueryString.init; }	return QueryString.str ? QueryString.str : null; }

QueryString.create = function( arr ) { var resarr = Array; for( var i in arr ) { if( typeof arr[i] == 'object' ){ var v = Array; for(var j in arr[i] ) { v[j] = encodeURIComponent( arr[i][j] ); }			resarr.push( encodeURIComponent( i ) + '=' + v.join('|')  ); } else { resarr.push( encodeURIComponent( i ) + '=' + encodeURIComponent( arr[i] ) ); }	}

return resarr.join('&');

}

QueryString.params = null; QueryString.str = null;

/**
 * Simple exception handling

Exception = function( str ) { this.str = str || ''; }

Exception.prototype.what = function { return this.str; }

/**
 * Status updating class

Status = function {}

/* Initiate an element to be a status window, it will remove all it's childs Status.init = function( elem ) {

if( !( elem instanceof Element ) ) { throw new Exception( 'object not an instance of Element' ); }

Status.elem = elem; Status.currentNode = null;

while( elem.hasChildNodes ) { elem.removeChild( elem.firstChild ); } }

// Private function Status.append = function( obj, node ) {

if( Status.elem == null ) { throw new Exception( 'no initialized object found' ); }

if ( ! ( obj instanceof Array ) ) { obj = [ obj ]; }

node = node || Status.currentNode;

for( var i in obj ) { if( typeof obj[i] == 'string' ) { node.appendChild( document.createTextNode( obj[i] ) ); } else { node.appendChild( obj[i] ); }	} }

Status.error = function( obj ) { Status.currentNode = document.createElement( 'div' ); Status.currentNode.style.color = 'OrangeRed'; Status.currentNode.style.fontWeight = '900'; Status.append( obj ); Status.elem.appendChild( Status.currentNode ); return Status.currentNode; }

Status.warn = function( obj ) { Status.currentNode = document.createElement( 'div' ); Status.currentNode.style.color = 'OrangeRed'; Status.append( obj ); Status.elem.appendChild( Status.currentNode ); return Status.currentNode; }

Status.info = function( obj ) { Status.currentNode = document.createElement( 'div' ); Status.currentNode.style.color = 'ForestGreen'; Status.append( obj ); Status.elem.appendChild( Status.currentNode ); return Status.currentNode; }

Status.debug = function( obj, level ) { level = level || 1; if( Status.debugLevel >= level ) { Status.currentNode = document.createElement( 'div' ); Status.currentNode.style.color = 'DimGray'; Status.append( "Debug (" + level + "): " ); Status.append( obj ); Status.elem.appendChild( Status.currentNode ); return Status.currentNode; } else { return null; } }

Status.debugLevel = 0;

Status.status = function( obj ) { Status.currentNode = document.createElement( 'div' ); Status.currentNode.style.color = 'SteelBlue'; Status.append( obj ); Status.elem.appendChild( Status.currentNode ); return Status.currentNode; }

Status.progress = function ( obj, node ) { Status.append( obj, node ); }

// Simple helper function to create a simple node function htmlNode( type, content, color ) { var node = document.createElement( type ); if( color ) { node.style.color = color; }	node.appendChild( document.createTextNode( content ) ); return node; }

// A simple dragable window

function SimpleWindow( width, height ) { this.width = width; this.height = height; this.frame = document.createElement( 'div' ); SimpleWindow.frames.push( this.frame ); this.topbar = document.createElement( 'div' ); this.topbarover = document.createElement( 'div' ); this.closeButton = document.createElement( 'span' ); this.frame.appendChild( this.topbar ); this.topbarover.appendChild( this.closeButton );

this.frame.style.zIndex = 100; this.frame.style.width = width + 'px'; this.frame.style.height = height + 'px'; this.frame.style.position = 'fixed'; this.frame.style.background = 'AliceBlue'; this.frame.style.border = '2px ridge Black'; this.frame.simpleWindow = this; this.frame.addEventListener( 'mousedown', this.focus, true );

this.closeButton.appendChild( document.createTextNode( '[close]' ) ); this.closeButton.style.position = 'absolute'; this.closeButton.style.fontWeight = '100'; this.closeButton.style.fontSize = '0.7em'; this.closeButton.style.top = '0px'; this.closeButton.style.left = '0px'; this.closeButton.style.cursor = 'pointer'; this.closeButton.simpleWindow = this; this.closeButton.addEventListener( 'click', this.close, false );

this.topbar.style.width = '100%'; this.topbar.style.height = '20px'; this.topbar.style.background = 'LightSteelBlue'; this.topbar.style.position = 'absolute'; this.topbar.style.fontWeight = '900'; this.topbar.style.fontSize = '1em'; this.topbar.style.fontFamily = 'sans-serif'; this.topbar.style.textAlign = 'center'; this.topbar.style.verticalAlign = 'baseline'; this.topbar.style.top = '0px'; this.topbar.style.left = '0px';

this.topbarover.style.width = '100%'; this.topbarover.style.height = '24px'; this.topbarover.style.position = 'absolute'; this.topbarover.style.top = '0px'; this.topbarover.style.left = '0px'; this.topbarover.simpleWindow = this; this.topbarover.addEventListener( 'mousedown', this.beginMove, true );

}

SimpleWindow.prototype.focus = function(e) { for( var i in SimpleWindow.frames ) { SimpleWindow.frames[i].style.zIndex = 99; }

this.simpleWindow.frame.style.zIndex = 100;

}

SimpleWindow.prototype.display = function {

this.title = this.title || "Title"; this.content = this.content || document.createTextNode( "" ); this.topbar.appendChild( document.createTextNode( this.title ) );

var content = document.createElement( 'div' ); content.style.position = 'relative'; content.style.top = '20px'; content.style.height = ( this.height - 20 ) + 'px'; content.style.overflow = 'auto'; content.appendChild( this.content ); this.frame.appendChild( content ); this.frame.appendChild( this.topbarover ); this.frame.style.width = this.width + 'px'; this.frame.style.height = this.height + 'px';

this.frame.style.top = (window.innerHeight - this.height )/2 + 'px' ; this.frame.style.left = (window.innerWidth - this.width )/2 + 'px'; document.getElementsByTagName('body')[0].appendChild( this.frame ); }

SimpleWindow.prototype.close = function(e) { if( e ) { this.simpleWindow.frame.parentNode.removeChild(this.simpleWindow.frame); } else { this.frame.parentNode.removeChild(this.frame); } }

SimpleWindow.prototype.setWidth = function( width ) { this.width = width; }

SimpleWindow.prototype.setHeight = function( height ) { this.height = height; }

SimpleWindow.prototype.setTitle = function( title ) { this.title = title; }

SimpleWindow.prototype.setContent = function( content ) { this.content = content; }

SimpleWindow.frames = [];

SimpleWindow.prototype.currentObject = null;

SimpleWindow.prototype.beginMove = function(e) { if( e.button != 0 ) { return; }	this.simpleWindow.initX = e.layerX; this.simpleWindow.initY = e.layerY; this.simpleWindow.lastX = e.clientX; this.simpleWindow.lastY = e.clientY; SimpleWindow.currentObject = this.simpleWindow;

window.addEventListener( 'mousemove', SimpleWindow.moveWindow, false ); window.addEventListener( 'mouseup', function(e) { 		SimpleWindow.currentObject = null;		window.removeEventListener( 'mousemove', SimpleWindow.moveWindow, false );		window.removeEventListener( 'mouseup', SimpleWindow.moveWindow, false );	}, false ); }

SimpleWindow.moveWindow = function(e) { if( SimpleWindow.currentObject == null ) { return; }	var y = e.clientY - SimpleWindow.currentObject.initY; var x = e.clientX - SimpleWindow.currentObject.initX;

SimpleWindow.currentObject.frame.style.top = y + 'px'; SimpleWindow.currentObject.frame.style.left = x + 'px'; e.stopPropagation; }