var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1;
var isMoz = document.implementation && document.implementation.createDocument;


////////////////////////////////////////////////////////////////////////

function ReplaceDivImage(DivId, NewUrl, applyFilter)
{
	var Div = elem(DivId);

	if (applyFilter && isIE)
	{
		if (Div.style.filter.length == 0)
		{
			//Div.style.filter = 'progid:DXImageTransform.Microsoft.Fade(Overlap=1.00, duration=0.2)'; 
			Div.style.filter = 'progid:DXImageTransform.Microsoft.RandomDissolve(duration=0.5)'; 
			 
		}

		Div.filters[0].apply();
		Div.filters[0].play();
	}

	Div.style.backgroundImage = 'url(' + NewUrl + ')'; 

	/*
	if (isIE)
	{
		
	}
	else
	{
		Div.style.backgroundImage = 'url(' + NewUrl + ')'; 
	}
	*/
}

function StartDelayed(FuncName)
{
	Wait();
	self.setTimeout("DelayedTimerTick('" + FuncName + "')", 20);
}
    
function DelayedTimerTick(FuncName)
{
		eval(FuncName + "()");
}

//////////////////
 
function ArrayList(Size) 
 {
	if (Size == 0 || Size == null) 
	{
		Size = 100;
	}
	
	this.data = new Array(Size);
	this.increment = Size;
	this.Count = 0;
	
	this.GetAt = GetAt;
	this.Insert = Insert;
	this.Add = Add;
	this.Clear = Clear;
	this.IndexOf = IndexOf;
	this.Contains = Contains
	this.resize = resize;
	this.clone = clone;
}
 
function getCapacity() 
{
	return this.data.length;
}
   
function GetAt(i) 
{
	try 
	{
		return this.data[i];
	} 
	catch (e) 
	{
		return "GetAt() " + e + " " + i;	
	}	
}

function Insert(obj, index) 
{
	try 
	{
		if (this.Count == this.capacity) 
		{
			this.resize();
		}
		
		for (var i = this.Count; i > index; i--) 
		{
			this.data[i] = this.data[i-1];
		}
		
		this.data[index] = obj;
		this.Count++;
	}
	catch (e) 
	{
		return "Invalid index " + i;
	}
}
 
function Add(obj) 
{
	if(this.Count == this.data.length) 
	{
		this.resize();
	}
	
	this.data[this.Count++] = obj;
}
 
function Clear() 
{
	this.Count = 0;
	
	for (var i=0; i < this.data.length; i++) 
	{
		this.data[i] = null;
	}
}
 
function IndexOf(obj) 
{
	for (var i=0; i < this.Count; i++) 
	{
		if (this.data[i] == obj) 
		{
			return i;
		}
	}
	return -1;
}
 
function Contains(obj) 
{
	for (var i = 0; i < this.Count; i++) 
	{
		if (this.data[i] == obj) 
		{
			return true;
		}
	}
	return false;
}
 
function resize() 
{
	newData = new Array(this.data.length + this.increment);
	
	for	(var i = 0; i< this.data.length; i++) 
	{
		newData[i] = this.data[i];
	}
	
	this.data = newData;
}
 
function clone() 
{
	var Al = new ArrayList(this.Count);
	
	for (var i = 0; i < this.Count; i++) 
	{
		Al.Add(this.data[i]);
	}
	
	return Al;
}

/////////////////////////////////////////////////////////////////////

function Hashtable()
{
	this.clear = _clear;
	this.containsKey = _containsKey;
	this.containsValue = _containsValue;
	this.get = hashtable_get;
	this.put = _put;
	this.isEmpty = _isEmpty;
	this.keys = _keys;
	this.remove = _remove;
	this.size = _size;
	this.values = _values;
	this.hashtable = new Array();
}                

function _clear()
{
	this.hashtable = new Array();
}

function _containsKey(key)
{
	var exists = false;
	for (var i in this.hashtable) 
	{
		if (i == key && this.hashtable[i] != null) 
		{
			exists = true;
			break;
		}
	}
	return exists;
}

function _containsValue(value)
{
	var contains = false;
	if (value != null) 
	{
		for (var i in this.hashtable) 
		{
			if (this.hashtable[i] == value) 
			{
				contains = true;
				break;
			}
		}
	}
	return contains;
}

function hashtable_get(key)
{
	return this.hashtable[key];
}

function _isEmpty()
{
	return (this.size == 0) ? true : false;
}

function _keys()
{
	var keys = new Array();
	for (var i in this.hashtable) 
	{
		if (this.hashtable[i] != null) 
			keys.push(i);
	}
	return keys;
}

function _put(key, value)
{
	if (key == null || value == null) 
	{
		throw "key or value null {" + key + "},{" + value + "}";
	}
	else
	{
		this.hashtable[key] = value;
	}
}

function _remove(key)
{
	var r = this.hashtable[key];
	this.hashtable[key] = null;
	return r;
}

function _size()
{
	var size = 0;
	
	for (var i in this.hashtable) 
	{
		if (this.hashtable[i] != null) 
			size ++;
	}
	return size;
}

function _values()
{
	var values = new Array();
	
	for (var i in this.hashtable) 
	{
		if (this.hashtable[i] != null) 
		{
			values.push(this.hashtable[i]);
		}
	}
	
	return values;
}

/////////////////////////////////////////////////////////////////////

function Remoting() 
{
	this.status;
	this.Ok = false;
	this.TimeOut = 5000;
	 
	this.XmlHttp = this.GetHttpObject();
	this.timeoutId;
	this.Response;
}

Remoting.prototype.GetHttpObject = function()
{ 
	var xmlhttp;
	
	if (document.all)
      xmlhttp = new ActiveXObject('MSXML2.XMLHTTP');
    else
      xmlhttp = new XMLHttpRequest();
	return xmlhttp;
}

Remoting.prototype.AsyncRxComplete = function(obj)
{
}

function GetDom(strXml)
{
	var _doc = null;

	if (isIE)
	{
		_doc = new ActiveXObject("Msxml2.DOMDocument.3.0");
		_doc.loadXML(strXml); 
	}
	else
	{
		var parser = new DOMParser();
		_doc = parser.parseFromString(strXml, "text/xml");
	}

	return _doc;
}

/// send synchronously
Remoting.prototype.SendSync = function(Data, timeout)
{
	this.TimeOut = timeout;
	
	var thePage = window.location.pathname + window.location.search;
	
	var oThis = this;
	
	this.Response = null;
	
	if(this.XmlHttp != null)
	{
		if( this.XmlHttp.readyState == 4 || this.XmlHttp.readyState == 0 )
		{
			this.XmlHttp.open('POST', thePage, false);
			this.XmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			this.timeoutId = window.setTimeout(oThis.TimiOutTriggered, timeout); 
			this.XmlHttp.send(Data);
			this.Response = this.XmlHttp.responseText;
			window.clearTimeout(this.timeoutId);
			
			if(this.XmlHttp.status == 200 && this.XmlHttp.statusText == "OK")
			{
				return this.Response;
			}
			else
			{
				return "Error";
			}
		}
	}
	
	return this.Response;
}

Remoting.prototype.TimiOutTriggered = function()
{
	if(this.XmlHttp)
	{
		this.XmlHttp.abort();
		this.Response = "TimeOut";
	}
}

Remoting.prototype.Send = function(Obj)
{
	var params = new Array();
	params.push(Obj);
	var oThis = this;
	return oThis.Invoke('NoMethod', params);	
}

Remoting.prototype.SendAsync = function(Obj)
{
	var params = new Array();
	params.push(Obj);
	
	var RObj = new RemoteObject_V3(); 
	RObj.Params = params;
	RObj.MethodName = 'NoMethod';
	
	var ht = new Hashtable();	
	
	ht.put('RemoteObject_V3_key', RObj);
	
	var s = xmlize(ht);
	
	var data = BuildData('', s);
	
	var thePage = window.location.pathname + window.location.search;
	
	if( this.XmlHttp.readyState == 4 || this.XmlHttp.readyState == 0 )
    {
      var oThis = this;
      this.XmlHttp.open('POST', thePage, true);
      this.XmlHttp.onreadystatechange = function(){ oThis.ReadyStateChange(); };
      this.XmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      this.XmlHttp.send(data);
    }
}

Remoting.prototype.ReadyStateChange = function()
{
  if( this.XmlHttp.readyState == 4)
  {
    if( this.XmlHttp.status == 0)
    {
      this.OnAbort();
    } 
    else if( this.XmlHttp.status == 200 && this.XmlHttp.statusText == "OK")
    {
		var _doc = GetDom(this.XmlHttp.responseText); 
		var Ret_obj = Deserial(_doc.childNodes[0]);  
		this.status = Ret_obj.Status;
		this.Ok = Ret_obj.OK;
		this.AsyncRxComplete(Ret_obj.Res); 
    }
    else
    {
		this.OnError(this.XmlHttp.status, this.XmlHttp.statusText, this.XmlHttp.responseText);   
    }
  }
}

Remoting.prototype.OnError = function(status, statusText)
{
  // Error
}

Remoting.prototype.Invoke = function(ServMethodName, params)
{
	if (params == null)
	{
		params = new Array();
	}
	
	var RObj = new RemoteObject_V3(); 
	RObj.Params = params;
	RObj.MethodName = ServMethodName;
	
	var ht = new Hashtable();	
	
	ht.put('RemoteObject_V3_key', RObj);
	
	var s = xmlize(ht);
	
	var data = BuildData('', s);
	
	var Res = this.SendSync(data, this.TimeOut);
	
	if (Res == "TimeOut")
	{
		this.status = "TimeOut";
		return null;
	}

	var _doc = GetDom(Res); 
	 
	var Ret_obj = Deserial(_doc.childNodes[0]); 
	 
	this.status = Ret_obj.Status;
	this.Ok = Ret_obj.OK;
	return Ret_obj.Res;
}

/// workaround  mozilla bug
// all the time the hidden field name is new 
// because when click "Reload" on Mozilla the hidden field with serialized data is empty
function GetForwardHiddenField()
{
	var Name = document.getElementsByName('SerializeField_Forward_name')[0].value;
	var TextField = document.getElementsByName(Name)[0];
	return TextField;
}

// typically after the page is loaded
function GetObj()
{
	try
	{
		var TextField = GetForwardHiddenField(); 
		var strXml = TextField.value;
		var _doc = GetDom(strXml);
		var Xelement = _doc.childNodes[0];
		var obj = Deserial(Xelement);  
		TextField.value = '';
		return obj;
	}
	catch(e)
	{
		//var g = 0;
	}
}

function Clone(obj)
{
	var s = xmlize(obj);
	return Des(s);
}

function BuildData(eventTarget, XML_eventArgument)
{
  var theData = '';
  var theform = document.forms[0];
  var thePage = window.location.pathname + window.location.search;
  var eName = '';
 
  theData  = '__EVENTTARGET='  + escape(eventTarget.split("$").join(":")) + '&';
 
  theData += '__EVENTARGUMENT=' + XML_eventArgument + '&';
  
  theData += '__XMLARG=' + XML_eventArgument + '&';
  
  theData += 'IsCallBack=true&';
  
  return theData;
}

function elem(id)
{
	return document.getElementById(id);
}

function _ClearHash()
{
	if (HashObject != null)
	{
		HashObject.clear(); 
	}
	
	GetForwardHiddenField().value = '';
}

function _Put(Key, Val)
{
 	HashObject.put(Key, Val);
}

function _Get(name)
{
	try
	{
		if (name == null)
		{
			return HashObject;
		}
		
		if (HashObject != null)
		{
			return HashObject.get(name);
		}
	}
	catch(e)
	{
		return null;
	}
	
	return null;
}

/// get the contol 
function GetControl(ID)
{
	try
	{
		if (HashObject != null)
		{
			var ControlsHt =  HashObject.get('ControlsUniqIdsHt_6XERT');
			var ControlID = ControlsHt.get(ID);
			var elem = document.getElementById(ControlID); 
			return elem;
		}
	}
	catch(e)
	{
		return null;
	}
	
	return null;
}

function Pre_PostBack(obj)
{
	if (obj == null)
	{
		obj = HashObject;
	}
	
	var ht = new Hashtable();	
	ht.put('PostBackObject', obj);
	var s = xmlize(ht);
	document.getElementsByName('SerializeField_PostBack')[0].value = s;
	document.forms[0].submit();
}

function Des(XmlText)
{
	var _doc = GetDom(XmlText); 
	return Deserial(_doc.childNodes[0]);
}

function Deserial(xn)
{
	var RetObj; 
	 
	var NodeType = "object";
	
	if (xn.attributes != null && xn.attributes.length != 0)
	{
		var tmp = xn.attributes.getNamedItem("type");
		if (tmp != null)
		{
			NodeType = xn.attributes.getNamedItem("type").nodeValue;
		}
	}
	
	if (IsSimpleVar(NodeType))
	{
		if (isIE)
		{
			return StringToObject(xn.text, NodeType);
		}
		else
		{
			return StringToObject(xn.textContent, NodeType);
		}
	}
	
	switch(NodeType)
	{
		case "array":
		{
			RetObj = [];
			
			for(var i = 0; i < xn.childNodes.length; i++)
			{
				var Node = xn.childNodes[i];
				RetObj[i] = Deserial(Node);
			}
			
			return RetObj;
		}
		
		case "Hashtable":
		{
			RetObj = new Hashtable();
			
			for(var i = 0; i < xn.childNodes.length; i++)
			{
				var Node = xn.childNodes[i];
				var Key = Node.nodeName;
				var NodeVal = Deserial(Node);
				RetObj.put(Key, NodeVal);
			}
			
			return RetObj;
		}
		break;
		
		case "ArrayList":
		{
			RetObj = new ArrayList();
			
			for(var i = 0; i < xn.childNodes.length; i++)
			{
				var Node = xn.childNodes[i];
				var NodeVal = Deserial(Node);
				RetObj.Add(NodeVal);
			}
			
			return RetObj;
		}
		break;
		
		case "object":
		default:
		{
			try
			{
				RetObj = eval("new "+ NodeType + "()");
			}
			catch(e)
			{
				// if no prototype of the class found
				RetObj = new Object();
			}
		}
		break;
	}
	
	for(var i = 0; i < xn.childNodes.length; i++)
	{
		var Node = xn.childNodes[i];
		RetObj[Node.nodeName] = Deserial(Node);
	}

	return RetObj;
}

function IsSimpleVar(type)
{
	switch(type)
	{
		case "int":
		case "string":
		case "String":
		case "Number":
		case "number":
		case "Boolean":
		case "boolean":
		case "bool":
		case "dateTime":
		case "Date":
		case "date":
		case "float":
			return true;
	}
	
	return false;
}

function StringToObject(Text, Type)
{
	var RetObj = null;

	switch(Type)
	{
		case "int":
			return parseInt(Text);   
			 
		case "number":
		{
			var outNum;
			
			if (Text.indexOf(".") > 0)
			{
				return parseFloat(Text);    
			}
			else
			{
				return parseInt(Text);    
			}
 		}	
			 	 
		case "string":
		case "String":
			return Text;
			 
		case "dateTime":
		case "date":
		case "Date":
			return new Date(Text);
		 		
		case "float":
			return parseFloat(Text, 10);
			
		case "bool":
			{
				if (Text == "true" || Text == "True")
				{
					return true;
				}
				else
				{
					return false;
				}
			}
			return parseBool(Text);	
	}

	return RetObj;  
}

function getClassName(obj) 
{
  return getMethodName(getConstructor(obj));
}
 
function getConstructor(obj) 
{
  return obj.constructor;
} 

function getMethodName(fn) 
{
  try 
  {
	var fnName = fn.toString();
	fnName = fnName.substring(fnName.indexOf("function")+ 8, fnName.indexOf('(')).replace(/ /g,'');
	return fnName;
  } 
  catch 
  (e) 
  {
   return "unknownType";
  }
 }
  
xmlize = function(ObjectToSerilize, objectName, indentSpace)
{
   indentSpace = indentSpace?indentSpace:'';
   
   var Type = GetTypeName(ObjectToSerilize);
    
   var s = indentSpace  + '<' + objectName +  ' type="' + Type + '">';
   
   switch(Type)
   {
		case "number":
		case "string":
		case "boolean":
		
		{
			s += ObjectToSerilize; 
		} 
   
		break;
	   
	   case "date":
	   {
			s += ObjectToSerilize.toLocaleString(); 
	   }
	   break;
	   
		case "array":
		{
			s += "\n";
				
				for(var name in ObjectToSerilize)
				{
					s += xmlize(ObjectToSerilize[name], ('index' + name ), indentSpace + "   ");
				};
				
				s += indentSpace;
		}
		break;
   
		case "Hashtable":
		{
			s += "\n";
			
			var Keys = ObjectToSerilize.keys();
			
			for(var i = 0; i < Keys.length; i++)
			{
				var KeyName = Keys[i];
				var Value = ObjectToSerilize.get(KeyName);
				s += xmlize(Value, KeyName , indentSpace + "   ");				
			}
		
		}
		break;
		
		case "ArrayList":
		{
			s += "\n";
			
			var Count = ObjectToSerilize.Count;
			
			for(var i = 0; i < Count; i++)
			{
				var Value = ObjectToSerilize.GetAt(i);
				s += xmlize(Value, ("index" + i), indentSpace + "   ");				
			}
		}
		break;
		
		default:
		{
			s += "\n";
			
			for(var name in ObjectToSerilize)
			{
				s += xmlize(ObjectToSerilize[name], name, indentSpace + "   ");
			};
			
			s += indentSpace;
		}
		break;

   }
   
	s += "</" + objectName + ">\n";	
     
    return s;
};

GetTypeName = function(ObjectToSerilize)
{
	if (ObjectToSerilize instanceof Array)
		return "array";
		
	if (ObjectToSerilize instanceof Date)
		return "date";	
		
	var Type  = typeof(ObjectToSerilize);

	if (IsSimpleVar(Type))
	{
		return Type;
	}
	
	Type = getClassName(ObjectToSerilize); 
	
	return Type;
}
  
/** 
 * Escape the given string chacters that correspond to the five predefined XML entities
 * @param sXml the string to escape
 */
/*
escape = function(sXml)
{
    return sXml.replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&apos;");
};
*/
/** 
 * Unescape the given string. This turns the occurences of the predefined XML 
 * entities to become the characters they represent correspond to the five predefined XML entities
 * @param sXml the string to unescape
 */
/*
unescape = function(sXml)
{
    return sXml.replace(/&apos;/g,"'")
        .replace(/&quot;/g,"\"")
        .replace(/&gt;/g,">")
        .replace(/&lt;/g,"<")
        .replace(/&amp;/g,"&");
};
*/
 