if (!Array.prototype.push)
	Array.prototype.push = function (i){
		this[this.length] = i;
	}
//---------------------------------------------------------------------------------------------------
function trim(str)
{
	return String(str).replace(/\s+$/,"").replace(/^\s+/,"");
}
String.prototype.trim = function()
{
	return this.replace(/\s+$/,"").replace(/^\s+/,"");
}
//----------------------------------------------------------------------------------------
// returns an object from a string, for example:
// 'a=b;c=d;e=f' will produce {'a':'b','c':'d','e':'f'}
// default values of separators: '=' and ';' are configurable
function makeObject(str,fieldsep,valuesep)
{
	if (typeof(str)!="string")
		return null;
	var fieldrx = fieldsep || ";";
	var valuerx = valuesep || "=";
	var stack = [],obj = {},mode=0;
	var lastkey="";
	var arr = str.split(fieldrx);
	for (var i in arr)
	{
		if (typeof (arr[i]) == "function")
			continue;
		switch(arr[i])
		{
		case "{":
			stack.push([obj,lastkey])
			obj = {};
			break;
		case "}":
			tmp = stack.pop();
			tmp[0][tmp[1]]=obj;
			obj = tmp[0];
			break;
		default:
			tmp =  arr[i].split(valuerx);
			if (tmp.length > 2)
			{
				var q = tmp.slice(1).join(valuerx);
				tmp = [tmp[0],q];
			}
			lastkey =trim(tmp[0]); 
			switch(tmp.length)
			{
			case 2: obj[lastkey]=trim(tmp[1]); break;
			case 1: obj[lastkey]=1; break;
			default: SiteError(" Hmm. Strange but split returns zero-element array");		
			}
		}
	}
	return obj;
}
//----------------------------------------------------------------------------------------
// returns an Array which elements are i,i+1,...j-1,j if i>j and vice versa otherwise.
// if one argument supplied range from 0 to that argument is created
function range(i,j)
{
	if (typeof(j) == "undefined")
	{
		j=i;
		i=0;
	}
	if (i > j)
	{
		var temp=i; i=j; j=temp;
	}
	var arr=new Array()
	for (var k =i;k<j;k++)
		arr.push(k);
	return arr;
}
//----------------------------------------------------------------------------------------
// dumps an object
function dump(obj,name)
{
	return "var " + name + "=" + _dump(obj,name);
}
//----------------------------------------------------------------------------------------
function _dump(obj,name)
{
	var txt="";
	switch (typeof (obj))
	{
	case "object":
		if (obj.constructor == Array)
		{
			txt+= " new Array(" + obj.length + ");\n";
			for (var i=0;i<obj.length;i++)
				txt+=name + "[" + i + "]=" + _dump(obj[i],name + "[" + i + "]")  ;
		}
		else if (obj.constructor == Date)
			txt+= " new Date(" + obj.valueOf() + "'));\n";
		else if (obj.constructor  == RegExp)
			txt+= String(obj) + ";";
		else
		{
			txt+= " new Object();\n";
			for (var  i in obj)
				if(!(typeof(obj[i]) == "function"))
					txt+= name + "['" + i + "']=" + _dump(obj[i],name + "['" + i + "']");
		}
		break;
	case "number":
		txt+=String(obj) +  ";\n";
		break;
	case "undefined":
		txt+="null;\n";
		break;
	case "string":
		txt+="'" + obj.replace(/([\'\\])/g,"\\$1") + "';\n";
		break;
	default:
		txt +=String(obj) + ";\n";
	}
	return txt;
}
//----------------------------------------------------------------------
String.esc_rx =new RegExp("([\\\'])","g");
String.nl_rx  =new RegExp("\\r?\\n","g");
//-------------------------------------------------------------------------
// forms one line to prevent Jscript line from breaking with ' or \n
String.prototype.escape = function()
{
	return (this.replace(String.nl_rx,"\\n")).replace(String.esc_rx,"\\$1");
}
//-------------------------------------------------------------------------
// dumps a string
String.prototype.dump = function()
{
	return "'" + this.escape() + "'";
}
//-------------------------------------------------------------------------
// dumps a  number
Number.prototype.dump = function()
{
	return this;
}
//-------------------------------------------------------------------------
// dumps a RegExp
RegExp.prototype.dump = function()
{
	return String(this).escape(); 
}
//-------------------------------------------------------------------------
// returns regexp which match valid dates format is number which is 101 for mm/dd/yyyy date format
// 120 for yyyy-mm-dd format. Other format from SQL Convert functions are not supported yet
Date.getRegExp = function(format)
{
	var day30 = '(30|[12][0-9]|0?[1-9])';
	var day30m = '(11|0?[469])';
	var day31 = '(3[01]|[12][0-9]|0?[1-9])';
	var day31m = '(1[02]|0?[13578])';
	var day28 =  '(2[0-8]|1[0-9]|0?[1-9])';
	var day29 = '([12][0-9]|0?[1-9])';
	
	var leap  =   '\\d\\d([02468][048]|[13579][26])';
	var nonleap = '\\d\\d([02468][1235679]|[13579][01345789])';
	var res = "";
	switch (format)
	{
	case 120:
			res = "(" + leap + "-(0?2-" + day29 + "|" + day31m + "-" + day31 + "|" +
				 day30m + "-" + day30 + ")|" + 
				 nonleap + "-(0?2-" + day28 + "|" + day31m + "-" + day31 + "|" +
				 day30m + "-" + day30 + "))";
			break;
	case 101: 
	default: res  = "(" + day31m + "/" + day31 + "|" +
					day30m + "/" + day30 + ")/\\d\\d\\d\\d|" + 
					"0?2/(" + day28 + "/" + nonleap + "|" +
					"" + day29 + "/" +leap + ")";
					break;
	}
	return  res;
}
//----------------------------------------------------------------------------------------------------
Date.months = new Array('January','February','March','April','May',
						'June','July','August','September','October',
						'November','December');
Date.days = new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
//---------------------------------------------------------------------------------------------------
// converts date to string according format string.
Date.prototype.toFormatString = function (date_format) {
// date format:
//	d 		- date (2 digits)
//	lday	-	full day name
//	sday	-	three letters shortening day
//	m		-	month (two digits)
//	mon		-	month (three-letter shortening)
//	month	-	full month's name
//	y		-	two digits year
//	Y		-	four digits year
	var res=date_format || "d/m/Y";
	var subst={};
	var d =this.getDate();
	subst['d'] = String(d).length == 1 ? "0" + String(d) : String(d);
	var m = this.getMonth()+1;
	subst['m'] = String(m).length == 1 ? "0" + String(m) : String(m);
	subst['month'] = Date.months[this.getMonth()];
	subst['mon'] = subst['month'].substr(0,3);
	subst['lday'] = Date.days[this.getDay()]
	subst['sday'] = subst['lday'].substr(0,3);
	var min = this.getMinutes();
	subst['min'] = String(min).length == 1 ? "0" + String(min) : String(min);
	var h = this.getHours();
	subst['h'] = String(h).length == 1 ? "0" + String(h) : String(h);
	var s = this.getSeconds();
	subst['s'] = String(s).length == 1 ? "0" + String(s) : String(s);
	subst['Y'] = String(this.getFullYear());
	subst['y'] = subst['Y'].substr(2);
	var rx = new RegExp("(?:mon(?:th)?|[ls]day|m[oi]n|[dmhsyY])","g");
	var rxfunc = function($0){return subst[$0]};
	return res.replace(rx,rxfunc);
}
//---------------------------------------------------------------------------------------------------
// dumps a Date
Date.prototype.dump = function()
{
	return "new Date(" + this.valueOf() + ")";
}
//----------------------------------------------------------------------
//Dumps an object
Object.prototype.dump=function()
{
	var txt="";
	for (var i in this)
	{
		if (this[i] == null)
			txt +=i.dump() + ":null,";
		else if (typeof (this[i]) == "function")
			continue;
		else if (this[i].dump)
			txt+=i.dump() + ":" + this[i].dump() + ",";
		else if (this[i].constructor ==   ActiveXObject)
			txt +=i.dump() + ": new ActiveXObject(),";
		else
			txt +=i.dump() + ":" + String(this[i]) + ",";
	}
	return "{" + txt.substring(0,txt.length-1) + "}";
}
//-------------------------------------------------------------------------
// Dumps an array
Array.prototype.dump = function()
{
	var txt="";
	for (var i=0;i<this.length;i++)
	{
		if (this[i] == null)
			txt +="null,";
		else if (this[i].dump)
			txt+=this[i].dump() + ",";
		else
			txt +=String(obj) + ",";
	}
	return "[" + txt.substring(0,txt.length-1) + "]";
}
//----------------------------------------------------------------------
// Returns Array of keys (properties) of an objec(order matches properties creation order)t
Object.prototype.keys=function()
{
	var k = new Array();
	for (var i in this)
	{
		if (typeof(this[i]) == "function")
			continue;
		k.push(i);	
	}
	return k;
}
//----------------------------------------------------------------------
// Returns an Array of values of an object (order matches properties creation order)
Object.prototype.values=function()
{
	var k = new Array();
	for (var i in this)
	{
		if (typeof(this[i]) == "function")
			continue;
		k.push(this[i]);	
	}
	return k;
}
//----------------------------------------------------------------------
//returns an Array of Arrays [key,value] from an object
Object.prototype.items=function()
{
	var k = new Array();
	for (var i in this)
	{
		if (typeof(this[i]) == "function")
			continue;
		k.push(new Array(i,this[i]));	
	}
	return k;
}
//----------------------------------------------------------------------
// Corrects object's elements "in place"
// Takes function f(key,value) as a parameter and performs that function on
// each (key,value) pair in an Object (replacing value with function result)
Object.prototype.correct = function(filterfunc)
{
	if (!(typeof(filterfunc)  == "function"))
		return ;
	for (var i in this)
		if (!(typeof(this[i]) == "function"))
			this[i]=filterfunc(i,this[i]);
	return this;
}
//-------------------------------------------------------------------------
// Takes function f(key,value) as a parameter and performs that function on
// each (key,value) pair in an Object (deleting the key if function returnns false)
Object.prototype.filter = function(filterfunc)
{
	if (!(typeof(filterfunc) == "function"))
		return;
	for (var i in this)
		if (!(typeof(this[i]) == "function") && !filterfunc(i,this[i]))
			delete this[i]
	return this;
}
//-------------------------------------------------------------------------
//Adds properties of obj to an Object
Object.prototype.extend = function (obj)
{
	for (var i in obj)
	{
		if (typeof(obj[i]) == "function" )
			continue;
		this[i]=obj[i]
	}
	return this;
}
//-------------------------------------------------------------------------
// Maps (key, value) pair to new (key, value) and assigns it to new object
// Takes two functions as parameters the first is function returning new value
// the second is returning new key. If second function omitted the old key is used.
// Both functions take old (key,value) pair as its parmeters
Object.prototype.map = function(valuefunc,keyfunc)
{
	var o;
	if (this.constructor == Array && !(typeof(keyfunc) == "function"))
		o= new Array();
	else 
		o = new Object();
	if (!(typeof(valuefunc) == "function"))
	{
		for (var i in this)
			if (!(typeof(this[i]) == "function"))
				o[i]=this[i];
	}
	else if (!(typeof(keyfunc) == "function"))
	{
		for (var i in this)
			if (!(typeof(this[i]) == "function"))
				o[i]=valuefunc(i,this[i])
	}
	else
	{
		for (var i in this)
			if (!(typeof(this[i]) == "function"))
				o[keyfunc(i,this[i])]=valuefunc(i,this[i])
	}
	return o;	
}
//-------------------------------------------------------------------------
// Works like Object.prototipe.filter  except that leaves source object as is
// and returns new one.
Object.prototype.grep = function(filterfunc)
{
	var o = new Object();
	
	if (!(typeof(filterfunc) == "function"))
	{
		for (var i in this)
			if (!(typeof(this[i]) == "function"))
				o[i]=this[i];
	}
	else
	{
		for(var i in this)
			if (!(typeof(this[i]) == "function") && filterfunc(i,this[i]))
				o[i]=this[i]
	}
	return o;
}
//-------------------------------------------------------------------------
// worth to comment if JScript is 5.5 or greater
if (!Array.prototype.push){
	Array.prototype.push = function(value)
	{
		this[this.length]=value;
	}
}
//-------------------------------------------------------------------------
Array.prototype.shift = function(){
	if (this.length == 1)
		return this.pop();
	var ret = this[0];
	for (var i = 1;i<this.length;i++)
		this[i-1] = this[i];
	this.pop();
	return ret;
}
//-------------------------------------------------------------------------
Array.prototype.unshift = function(val){
	for (var i = 1;i<this.length;i++)
		this[i] = this[i - 1];
	return this[0] = val;
}
//-------------------------------------------------------------------------
// Like Object.prototype.grep but shrinks the Array as necessary
Array.prototype.grep = function(filterfunc)
{
	var j=0;o= new Array();
	if (!(typeof(filterfunc) == "function"))
	{
		for (var i in this)
			if (!(typeof(this[i]) == "function"))
				o[i]=this[i];
	}
	else
	{
		for(var i in this)
			if (!(typeof(this[i]) == "function") && filterfunc(i,this[i]))
				o[j++]=this[i];
	}
	return o;
}
//-------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////
// Maps array-like thingy (args) to new Object  (or real Array if keyfunc is omitted)
// Maps 1:1  if valuefunc omitted also. The need in this function is in that array-like
// thingy  (like 'arguments' in functions) does not have all the things real array does.
function mapArgs(args,valuefunc,keyfunc)
{
	var o;
	if (!(typeof(keyfunc) == "function"))
		o= new Array();
	else 
		o = new Object();
	if (!(typeof(valuefunc) == "function"))
	{
		for (var i=0;i<args.length;i++)
			o[i]=args[i];
	}
	else if (!(typeof(keyfunc) == "function"))
	{
		for (var i=0;i<args.length;i++)
			o[i]=valuefunc(i,args[i])
	}
	else
	{
		for (var i=0;i<args.length;i++)
			o[keyfunc(i,args[i])]=valuefunc(i,args[i])
	}
	return o;	
}
//-------------------------------------------------------------------------
// Similar to the above thing. Maps args to new real Array (those elements which
// a function supplied as argument returns true on
function grepArgs(args,filterfunc)
{
	var o = new Array();
	var j=0;
	
	if (!(typeof(filterfunc) == "function"))
	{
		for (var i=0;i<args.length;i++)
			o[i]=args[i];
	}
	else
	{
		for (var i=0;i<args.length;i++)
			if (filterfunc(i,args[i]))
				o[j++]=args[i]
	}
	return o;
}
//-------------------------------------------------------------------------
