/* Remoting.js
 *
 * Author: Jonas Jonsson (fatbrain@sphere.se)
 * Copyright (C) 2003-2004 Jonas Jonsson
 * All Rights Reserved 2003-2004
 */

function emptyFunction() {}

function IsArray(o) { return o != null && o.constructor == Array; }

function JavaScript()
{
	this.IsUndefined = function(o) { return typeof(o) == "undefined"; }
	this.HasProperty = function(propertyList, name)
	{
		return typeof(propertyList[name]) != "undefined";
	}
	this.GetProperty = function(propertyList, name, defaultValue)
	{
		if(!propertyList || typeof(propertyList[name]) == "undefined") return defaultValue;
		return propertyList[name];
	}

	/* Unicode Functions */
	function urlEncode(n)
	{
		return "%" + (n <= 15?"0"+n.toString(16):n.toString(16));
	}

	function createCache()
	{
		var utf8Cache = new Object();
		
		for(var c = 0; c < 255; c++)
		{
			if(c >= 0 && c <= 127)
				utf8Cache[c] = urlEncode(c); //(c < 48 || (c > 57 && c < 65) || (c > 90 && c < 97) || c > 122)?urlEncode(c):String.fromCharCode(c);
			else if(c >= 128 && c <= 191)
				utf8Cache[c] = "%c2" + urlEncode(c);
			else if(c >= 192 && c <= 255)
				utf8Cache[c] = "%c3" + urlEncode(c - 0x40);
		}
		
		return utf8Cache;
	}

	var utf8Cache = createCache();

	function char2Utf8(unicodeCharCode)
	{
		var utf8Char = "";
		var c = unicodeCharCode;
		var q = c <= 0x7f?0:c <= 0x7ff?1:c <= 0xffff?2:c <= 0x1fffff?3:c <= 0x3ffffff?4:5;
		var m = [ 0x0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc ][q];
		while(q-- > 0)
		{
			var n = 0x80 | (c & 0x3f);
			utf8Char = urlEncode(n) + utf8Char;
			c >>= 6;
		}
		utf8Char = urlEncode(m | c) + utf8Char;
		
		if(!utf8Cache[unicodeCharCode]) utf8Cache[unicodeCharCode] = utf8Char;
		return utf8Char;
	}

	function Unicode2Utf8(unicodeString)
	{
		if(!unicodeString) return "";
		
		var utf8String = "";
		
		for(var i = 0, c = unicodeString.charCodeAt(0); i < unicodeString.length; c = unicodeString.charCodeAt(++i))
		{
			utf8String += utf8Cache[c] || char2Utf8(c);
		}

		return utf8String;
	}

	this.Unicode2Utf8 = function(unicodeString)
	{
		return Unicode2Utf8(unicodeString);
	}
	
	this.createQueryString = function(paramList)
	{
		if(!paramList || typeof(paramList) != "object")
			return "";
			
		var parameterString = "";
		var oEmpty = {};
		for(var p in paramList)
		{
			if(!oEmpty[p])
			{
				var sName = js.Unicode2Utf8(p);
				var oValue = paramList[p];
				var sValue = "";
				
				if(IsArray(oValue))
				{
					for(var i = 0; i < oValue.length; i++)
						sValue += (sValue.length?"&":"") + sName + "=" + js.Unicode2Utf8(oValue[i].toString());
				}
				else if(oValue != null)
					sValue = sName + "=" + js.Unicode2Utf8(oValue.toString());
				
				parameterString += (parameterString?"&":"") + sValue;
			}
		}

		return parameterString;
	}
	
	this.deserializeJson = function(jsonString)
	{
		eval("var oJson = " + jsonString);
		return oJson;
	}
}

function getParam(paramList, name, defaultValue)
{
	if(!paramList || typeof(paramList) != "object" || typeof(paramList[name]) == "undefined") return defaultValue;
	return paramList[name];
}

// Extending intrinsic object Array //
Array.prototype.AddRange = function(range)
{
	for(var i = 0; i < range.length; i++)
		this.Add(range[i]);
}
Array.prototype.Add = function(obj)
{
	this.Insert(this.length, obj);
}
Array.prototype.Insert = function(n, obj)
{
	for(var i = this.length; i > n; i--)
		this[i] = this[i - 1];
	this[n] = obj;
}
Array.prototype.InsertRange = function(n, range)
{
	for(var i = 0; i < range.length; i++)
		this.Insert(n+i, range[i]);
}
Array.prototype.Remove = function(obj)
{
	for(var i = 0; i < this.length; i++)
		if(this[i] == obj)
			this.RemoveAt(i);
}
Array.prototype.RemoveAt = function(n)
{
	for(var i = n + 1; i < this.length; i++)
		this[i - 1] = this[i];
	this.length--;
}
Array.prototype.RemoveRange = function(n, count)
{
	while(count-- > 0)
		this.RemoveAt(n);
}
Array.prototype.IndexOf = function(obj, n)
{
	n = n || 0;
	for(var i = n; i < this.length; i++)
		if(this[i] == obj)
			return i;
	
	return -1;
}
Array.prototype.Contains = function(obj)
{
	return this.IndexOf(obj) > -1;
}
Array.prototype.Enqueue = function(obj)
{
	this.Add(obj);
}
Array.prototype.Dequeue = function()
{
	if(this.length > 0)
	{
		var obj = this[0];
		this.RemoveAt(0);
		return obj;
	}
	
	return null;
}

// Extending intrinsic object String //
String.prototype.IndexOf = function(text, n)
{
	return this.indexOf(text, n?n:0);
}
String.prototype.EndsWith = function(text)
{
	return this.IndexOf(text, this.length - text.length) > -1;
}
String.prototype.StartsWith = function(text)
{
	return this.IndexOf(text) == 0;
}
String.prototype.Substring = function(nStart, nLength)
{
	nLength = nLength || (this.length - nStart);
	return this.substr(nStart, nLength);
}
String.prototype.Insert = function(n, text)
{
	return this.Substring(0, n) + text + this.Substring(n);
}
String.prototype.Remove = function(n, count)
{
	return this.Substring(0, n) + this.Substring(n + count);
}
String.prototype.Split = function(c)
{
	return this.split(c);
}
String.prototype.ToLower = function()
{
	return this.toLowerCase();
}
String.prototype.ToUpper = function()
{
	return this.toUpperCase();
}
String.prototype.TrimStart = function()
{
	return this.replace(/$\s+/, "");
}
String.prototype.TrimEnd = function()
{
	return this.replace(/\s+^/, "");
}
String.prototype.Trim = function()
{
	return this.TrimStart().TrimEnd();
}
String.prototype.Append = function(text)
{
	return this + text;
}

// Extending intrinsic object Number //
Number.prototype.Unit = function(unit)
{
	return this.toString() + unit;
}

/*
Function.Call = function(fn, args)
{
	switch(args.length)
	{
		case 0: fn(); break;
		case 1: fn(args[0]); break;
		case 2: fn(args[0], args[1]); break;
		case 3: fn(args[0], args[1], args[2]); break;
		case 4: fn(args[0], args[1], args[2], args[3]); break;
		case 5: fn(args[0], args[1], args[2], args[3], args[4]); break;
		case 6: fn(args[0], args[1], args[2], args[3], args[4], args[5]); break;
		case 7: fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break;
		case 8: fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break;
		case 9: fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); break;
	}
}

Object.prototype.Constructor = function()
{
	var cArray = arguments;
	var args = arguments.callee.caller.arguments;
	for(var i = 0; i < cArray.length; i++)
		if(args.length == cArray[i][document.all?"length":"arity"])
		{
			Function.Call(cArray[i], args);
		}
}

function DateTime()
{
	this.Constructor(function(a) { alert(this.a); });
}
DateTime.prototype = new Date();
DateTime.prototype.constructor = Date.prototype.constructor;

var a = new DateTime(121212);
*/
/* Extending Mozilla */
//~ if(!document.all)
//~ {
	//~ function __attachEvent(domObject, sEvent, fpNotify)
	//~ {
		//~ var type = sEvent.StartsWith("on")?sEvent.Substring(2):sEvent;
		//~ var listener = fpNotify;
		//~ var useCapture = false;
		
		//~ domObject.addEventListener(type, listener, useCapture);
	//~ }
	
	//~ function __detachEvent(domObject, sEvent, fpNotify)
	//~ {
		//~ var type = sEvent.StartsWith("on")?sEvent.Substring(2):sEvent;
		//~ var listener = fpNotify;
		//~ var useCapture = false;
		
		//~ domObject.removeEventListener(type, listener, useCapture);
	//~ }
	
	//~ Window.prototype.attachEvent = function(sEvent, fpNotify)
	//~ {
		//~ __attachEvent(this, sEvent, fpNotify);
	//~ }
	//~ Node.prototype.attachEvent = function(sEvent, fpNotify)
	//~ {
		//~ __attachEvent(this, sEvent, fpNotify);
	//~ }
	//~ Window.prototype.detachEvent = function(sEvent, fpNotify)
	//~ {
		//~ __detachEvent(this, sEvent, fpNotify);
	//~ }
	//~ Node.prototype.detachEvent = function(sEvent, fpNotify)
	//~ {
		//~ __detachEvent(this, sEvent, fpNotify);
	//~ }
	
	//~ XMLDocument.prototype.__defineGetter__("xml", function() { return (new XMLSerializer()).serializeToString(this); });
	//~ XMLDocument.prototype.loadXML = function(xml)
	//~ {
		//~ var oldxml = this.xml;
		//~ var doc = (new DOMParser()).parseFromString(xml, "text/xml");
		
		//~ while(this.hasChildNodes())
			//~ this.removeChild(this.firstChild);
		
		//~ for(var i = 0, nodes = doc.childNodes; i < nodes.length; i++)
			//~ this.appendChild(this.importNode(nodes[i], true));
			
		//~ return oldxml;
	//~ }
	//~ XMLDocument.prototype.load = function(Url)
	//~ {
		//~ var oxmlhttp = getXmlHttpRequest();
		//~ oxmlhttp.open("GET", Url, false);
		//~ oxmlhttp.send(null);

		//~ var doc = oxmlhttp.responseXML;
		//~ for(var i = 0, nodes = doc.childNodes; i < nodes.length; i++)
			//~ this.appendChild(this.importNode(nodes[i], true));
	//~ }
//~ }

//~ // Extending intrinsic object Object //
//~ Object.prototype.EventHandler = function(whatEvent)
//~ {
	//~ function eventHandler(object, whatEvent)
	//~ {
		//~ var events = [];
	
		//~ object[whatEvent] = function()
		//~ {
			//~ if(arguments.length == 1 && typeof(arguments[0]) == "function")
			//~ {
				//~ events.Add(arguments[0]);
			//~ }
			//~ else
			//~ {
				//~ object[whatEvent].Invoke(arguments[0]);
			//~ }
		//~ }
		//~ object[whatEvent].Invoke = function(eventArgs)
		//~ {
			//~ for(var i = 0; i < events.length; i++)
				//~ events[i](eventArgs);
		//~ }
		//~ object[whatEvent].Clear = function() { events = []; }
	//~ }
	//~ new eventHandler(this, whatEvent);
//~ }

//~ Object.toSource = function(graph)
//~ {
	//~ var emptyObject = new Object();
	//~ var processed = new Object();
	
	//~ function function2String(v)
	//~ {
		//~ return "function() {}";
	//~ }
	
	//~ function string2String(v)
	//~ {
		//~ return "\"" + v.replace(/\\/g, "\\\\").replace(/\r/g, "\\r").replace(/\n/g, "\\n").replace(/\f/g, "\\f").replace(/\t/g, "\\t").replace(/"/g, "\\\"").replace(/'/g, "\\'") + "\"";
	//~ }
	
	//~ function object2String(graph)
	//~ {
		//~ if(graph in processed) return;
		//~ processed[graph] = true;
		
		//~ var s = "{";
		
		//~ for(var p in graph)
		//~ {
			//~ if(p in emptyObject)
				//~ continue;
				
			//~ var v = graph[p];

			//~ s += (s.length > 1?",":"") + p + ":";
			
			//~ if(v == null)
				//~ s += "null";
			//~ else if(typeof(v) == "string")
				//~ s += string2String(v);
			//~ else if(typeof(v) == "number")
				//~ s += v.toString();
			//~ else if(typeof(v) == "function")
				//~ s += function2String(v);
			//~ else if(typeof(v) == "boolean")
				//~ s += v.toString();
			//~ else if(typeof(v) == "object")
			//~ {
				//~ if(v.constructor == Array)
					//~ s += "[]";
				//~ else if(v.constructor == Date)
					//~ s += v.valueOf().toString();
				//~ else if(v.constructor == RegExp)
					//~ s += v.toString();
				//~ else
					//~ s += object2String(v);
			//~ }
		//~ }
		
		//~ s += "}";
		
		//~ return s;
	//~ }
	
	//~ if(typeof(graph) == "object")
		//~ return object2String(graph);
	//~ else if(typeof(graph) == "undefined")
		//~ return "undefined";
//~ }


//~ // Dom object //
//~ function Dom()
//~ {
	//~ var properties = [];
	//~ var events = [];

	//~ /* Properties */
	//~ function getProperty(domObject, sProperty)
	//~ {
		//~ for(var i = 0; i < properties.length; i++)
			//~ if(properties[i].domObject == domObject && properties[i].sProperty == sProperty)
				//~ return properties[i];
				
		//~ return null;
	//~ }
	
	//~ function deleteProperty(domObject, sProperty)
	//~ {
		//~ for(var i = 0; i < properties.length; i++)
			//~ if((!domObject || properties[i].domObject == domObject) && (!sProperty || properties[i].sProperty == sProperty))
			//~ {
				//~ try
				//~ {
					//~ properties[i].domObject[properties[i].sProperty] = properties[i].initialValue;
					//~ properties.RemoveAt(i);
					//~ i--;
				//~ }
				//~ catch(e)
				//~ {
					//~ alert(properties[i].sProperty);
				//~ }
			//~ }
	//~ }
	
	//~ this.getProperty = function(domObject, sProperty)
	//~ {
		//~ return domObject[sProperty];
	//~ }
	
	//~ this.setProperties = function(domObject, propertyValueList)
	//~ {
		//~ for(var p in propertyValueList)
		//~ {
			//~ if(typeof(propertyValueList[p]) == "object")
				//~ this.setProperties(domObject[p], propertyValueList[p]);
			//~ else if(typeof(propertyValueList[p]) == "string")
				//~ this.setProperty(domObject, p, propertyValueList[p]);
		//~ }
	//~ }

	//~ this.setProperty = function(domObject, sProperty, value, initialValue)
	//~ {
		//~ if(!document.all)
		//~ {
			//~ domObject[sProperty] = value;
			//~ return;
		//~ }
		
		//~ if(domObject && sProperty)
		//~ {
			//~ var prop = getProperty(domObject, sProperty);
			//~ if(prop == null)
				//~ properties.Add({ domObject: domObject, sProperty: sProperty, initialValue: js.IsUndefined(initialValue)?domObject[sProperty]:initialValue });
			
			//~ domObject[sProperty] = value;
		//~ }
	//~ }
	
	//~ this.deleteProperty = function(domObject, sProperty)
	//~ {
		//~ if(!document.all) return;
		//~ deleteProperty(domObject, sProperty);
	//~ }
	
	//~ this.removeChild = function(parentObject, childObject)
	//~ {
		//~ deleteProperty(childObject);
		//~ return parentObject.removeChild(childObject);
	//~ }
	
	//~ /* Events */
	//~ this.attachEvent = function(domObject, sEvent, fpNotify)
	//~ {
		//~ events.Add({ domObject: domObject, sEvent: sEvent, fpNotify: fpNotify });
		//~ try
		//~ {
			//~ domObject.attachEvent(sEvent, fpNotify);
		//~ }
		//~ catch(e)
		//~ {
			//~ alert(sEvent);
		//~ }
	//~ }
	
	//~ this.detachEvent = function(domObject, sEvent, fpNotify)
	//~ {
		//~ for(var i = 0; i < events.length; i++)
		//~ {
			//~ if((!domObject || events[i].domObject == domObject) && (!sEvent || events[i].sEvent == sEvent) && (!fpNotify || events[i].fpNotify == fpNotify))
			//~ {
				//~ events[i].domObject.detachEvent(events[i].sEvent, events[i].fpNotify);
				//~ events[i].domObject = null;
				//~ events[i].sEvent = null;
				//~ events[i].fpNotify = null;
				//~ events.RemoveAt(i);
				//~ i--;
			//~ }
		//~ }
	//~ }
	
	//~ function wrapEvent(evt)
	//~ {
		//~ var isIE = document.all?true:false;
		//~ this.target = isIE?evt.srcElement:evt.target;
		//~ this.keyCode = evt.keyCode;
		//~ this.ctrlKey = evt.ctrlKey;
		//~ this.shiftKey = evt.shiftKey;
		//~ this.altKey = evt.altKey;
		//~ this.keyString = (this.ctrlKey?"c":"") + (this.shiftKey?"s":"") + (this.altKey?"a":"") + this.keyCode;
		//~ this.clientX = evt.clientX;
		//~ this.clientY = evt.clientY;
		//~ this.relatedTarget = document.all?evt.fromElement:evt.relatedTarget;
		//~ this.screenX = evt.screenX;
		//~ this.screenY = evt.screenY;
		//~ this.layerX = document.all?evt.offsetX:evt.layerX;
		//~ this.layerY = document.all?evt.offsetY:evt.layerY;
		//~ this.type = evt.type;
		//~ this.preventDefault = function()
		//~ {
			//~ if(document.all)
				//~ evt.returnValue = false;
			//~ else
				//~ evt.preventDefault();
		//~ }
		//~ this.cancel = function()
		//~ {
			//~ if(document.all)
				//~ evt.cancelBubble = true;
			//~ else
				//~ evt.stopPropagation();
		//~ }
	//~ }
	
	//~ this.getEvent = function()
	//~ {
		//~ var evt = document.all?window.event:arguments.callee.caller.arguments[0];
		//~ return new wrapEvent(evt);
	//~ }

	//~ this.attachEvent(window, "onunload", function()
	//~ {
		//~ if(document.all)
		//~ {
			//~ dom.deleteProperty();
			//~ dom.detachEvent();
		//~ }
	//~ });
	
	//~ // Various Dom functions //
	//~ this.HasChild = function(parentObject, childObject)
	//~ {
		//~ if(parentObject == childObject)
			//~ return true;
		
		//~ if(parentObject.childNodes.length > 0)
		//~ {
			//~ for(var i = 0; i < parentObject.childNodes.length; i++)
				//~ if(this.HasChild(parentObject.childNodes[i], childObject))
					//~ return true;
		//~ }

		//~ return false;
	//~ }

	//~ this.getX = function(e) { return e.style.position == "absolute"?parseInt(e.style.left):dom.getOffset(e, "Left"); }
	//~ this.getY = function(e) { return e.style.position == "absolute"?parseInt(e.style.top):dom.getOffset(e, "Top"); }
	//~ this.getLoc = function(e) { return new Point(dom.getX(e), dom.getY(e)); }
	//~ this.getOffset = function(e, whatOffset)
	//~ {
		//~ for(var i = 0; e != null; i += e["offset" + whatOffset], e = e.offsetParent);
		//~ return i;
	//~ }
	//~ this.getWidth = function(e) { return e.offsetWidth + (document.all?(new Number(e.style.marginLeft) + new Number(e.style.marginRight)):0); }
	//~ this.getHeight = function(e) { return e.offsetHeight + (document.all?(new Number(e.style.marginTop) + new Number(e.style.marginBottom)):0); }
//~ }

//~ function Point(x, y)
//~ {
	//~ this.x = x;
	//~ this.y = y;
	//~ this.MoveBy = function(point) { this.x += point.x; this.y += point.y; return this; }
	//~ this.toString = function() { return this.x + "," + this.y; }
//~ }

//~ var dom = new Dom();
//~ var js = new JavaScript();
