var m_cpxsduri= "http://www.imsglobal.org/xsd/imscp_v1p1";

function CViewerObj()
{
 		//////////////////////////////////////////////////////////////////////
		//PRIVATE VARIABLES.
		//
		//These vars are not exposed to public references of this object.
		//////////////////////////////////////////////////////////////////////
		
		var m_oXMLDOM    = mf_CreateDOM();	//this xmldom is used to contain the entire course - imsmanifest.xml
		var m_oXSLDOM		 = mf_CreateDOM();	//this xmldom is used to contain the XSL - cpitem.xsl
		
		var m_nCntXMLLoaded	= 0;						// this variable counts loaded XML files
	
		var m_szCurrentNodeID = null;
		var m_oTimer = null;
		var m_strCurrentTOC = "";					//current toc index.
		var m_strCurrentManifest = "";
		var m_strXSLPath = "";					  //path to resources.
		var m_ClassURL = "";
		var m_oLMSAPI = null;

		var enum_SELECT_SINGLEITEM = 0;
		var enum_SELECT_ITEMCHILDREN = 1;
		var enum_SELECT_TOCS = 2;
		var enum_SELECT_TOC = 3;
	
		var enum_CPO_PREVIOUS = 0;
		var enum_CPO_NEXT = 1;
		var enum_CPO_SELECT = 2;
		var enum_CPO_INIT = 3;
		var enum_CPO_LESSONSTATUS = 4;
		var enum_CPO_EXITSTATUS = 5;
		
		var LMSAPI_LESSONSTATUS = 200;
		var LMSAPI_EXITSTATUS = 300;
		
		var m_fIsReady = false;

		//////////////////////////////////////////////////////////////////////
		//PUBLIC METHODS.
		//
		//These methods are exposed to public references of this object.
		//////////////////////////////////////////////////////////////////////
		this.m_myXMLDOM=m_oXMLDOM;
		this.m_myCurrentNodeID=null;

		CViewerObj.prototype.DoNext = function DoNext()
		{
			this.m_myCurrentNodeID=m_szCurrentNodeID;
			var szNodeID = m_szCurrentNodeID;
			var oNewCurrentNode = this.GetNext(szNodeID);

			if (oNewCurrentNode != null)
			{
				m_szCurrentNodeID = oNewCurrentNode.documentElement.childNodes[0].getAttribute("ID");
				mf_CreateEvent(enum_CPO_NEXT, m_szCurrentNodeID);
			}

			return ( oNewCurrentNode );
		}
		
		CViewerObj.prototype.DoPrevious = function DoPrevious()
		{
			this.m_myCurrentNodeID=m_szCurrentNodeID;
			var szNodeID = m_szCurrentNodeID;
			var oNewCurrentNode = this.GetPrevious(szNodeID);

			if (oNewCurrentNode != null)
			{
				m_szCurrentNodeID = oNewCurrentNode.documentElement.childNodes[0].getAttribute("ID");
				mf_CreateEvent(enum_CPO_PREVIOUS, m_szCurrentNodeID)
			}
			
			return ( oNewCurrentNode );
		}
		
		CViewerObj.prototype.DoSelect = function DoSelect(id)
		{
			this.m_myCurrentNodeID=m_szCurrentNodeID;
			var oNewCurrentNode = this.GetItem(id);

			if((oNewCurrentNode != null) )
			{
				if (m_oLMSAPI)
					if (m_oTimer)
					{
						var strTimeDelta = m_oLMSAPI.LRNGetScopedValue("cmi.core.total_time", m_szCurrentNodeID, true);
						strTimeDelta = m_oTimer.CalculateNewTimeDelta(strTimeDelta);
						m_oLMSAPI.LRNSetScopedValue("cmi.core.total_time", strTimeDelta, m_szCurrentNodeID, true);
					}
				m_szCurrentNodeID = id;
				if (m_oLMSAPI)				
					m_oLMSAPI.LRNSetScopedValue("cmi.core.entry", "resume", m_szCurrentNodeID, true);

				//will need to fire event.
				mf_CreateEvent(enum_CPO_SELECT, m_szCurrentNodeID);
			}							

			return ( oNewCurrentNode );
		}
		
		CViewerObj.prototype.DoSelectFirst = function  DoSelectFirst()
		{
			if (!m_oXMLDOM)	return (null);
			if (!m_oXMLDOM.documentElement) return (null);
				
			var oXMLCurrentNode = null;
			var oNewCurrentNode = null;
			
			// Rozbaleni vsech polozek pokud je jich mene nez 2 - krom prvni polozky ta bude vybrana nasledne
			/*	
			nl=m_oXMLDOM.documentElement.selectNodes("//organization[@identifier='" + m_strCurrentTOC + "']/item");

			if ((nl.length>0) && (nl.length<=2)) {
				for (i=1;i<nl.length;i++)
					this.DoSelect(nl[i].getAttribute("identifier"));
			}

			// Vybrani prvni hodnoty
			oXMLCurrentNode = m_oXMLDOM.documentElement.selectSingleNode("//organization[@identifier='" + m_strCurrentTOC + "']/item");
			if (oXMLCurrentNode) oNewCurrentNode = this.DoSelect(oXMLCurrentNode.getAttribute("identifier"))
			*/
			
			return oNewCurrentNode;
		}	
		
		CViewerObj.prototype.GetCurrent = function GetCurrent()
		{
			return this.GetItem(m_szCurrentNodeID);
		}
		
		CViewerObj.prototype.GetNext = function GetNext(id)  
		{
			if (!m_oXMLDOM) return null;
			
			var oNode = null;
			var oNextNode = null;
			var oNewNode = null;
			var szID = null;
			
			//get the relative node.
			
			if(id != null)
			{
				oNode = mf_FindItem(id);
					
				if (oNode)
					oNextNode = mf_FindNext(oNode,true);
			}
			else //id is null. return the first node.
				oNextNode = m_oXMLDOM.selectSingleNode("//organization[@identifier='" + m_strCurrentTOC + "']//item[0]");
			
			
			if (oNextNode)
			{
				szID = oNextNode.getAttribute("identifier");
			
				if (szID != null)
					oNewNode = mf_TransformFromIMStoMLT(szID, enum_SELECT_SINGLEITEM);
			}
			
			return oNewNode;
		}

		CViewerObj.prototype.GetPrevious = function GetPrevious(id)  
		{
			if (!m_oXMLDOM) return (null);
			
			var oNode = null;
			var oPrevNode = null;
			var oNewNode = null;
			var szID = null;
			
			//get the relative node.
			oNode = mf_FindItem(id);
			
			if (oNode)
				oPrevNode = mf_FindPrevious(oNode);
				
			if (oPrevNode)
			{
			
				szID = oPrevNode.getAttribute("identifier");
				
				if (szID != null)
					oNewNode = mf_TransformFromIMStoMLT(szID, enum_SELECT_SINGLEITEM) ;
			}
			
			return (oNewNode);
		}

		CViewerObj.prototype.GetParent = function GetParent(id)
		{
			if (!m_oXMLDOM) return null;
			
			var oParent = null;
			var oNewNode = null;
			var szID = null;		
		
			oParent = mf_FindParent(id);
				
			if (oParent)
			{
				szID = oParent.getAttribute("identifier") ;
				
				if (szID)
				{
					oNewNode = mf_TransformFromIMStoMLT(szID , enum_SELECT_SINGLEITEM);
				}
			}	
			
			return ( oNewNode ) ;
		}
		
		CViewerObj.prototype.InitRoutine = function InitRoutine()
		{
			m_nCntXMLLoaded++;
			if (m_nCntXMLLoaded>=2)
			{
				if (IsIE()) m_oXMLDOM.setProperty("SelectionNamespaces", "xmlns:cp='"+m_cpxsduri+"'"); // NS se kvůli opeře nepoužívají
				// Získání defaultní nebo první organizace
				orgs = m_oXMLDOM.selectSingleNode("manifest/organizations");
				m_strCurrentTOC = m_oXMLDOM.selectSingleNode("manifest/organizations").getAttribute("default");
				if (!m_strCurrentTOC)  m_strCurrentTOC = m_oXMLDOM.selectSingleNode("manifest/organizations/organization[0]").getAttribute("identifier");

				m_oTimer = new Timer();
				mf_CreateEvent(enum_CPO_INIT, null);
				if (m_oLMSAPI) m_oLMSAPI.LRNListenForEvents(mf_EventHandler);
				m_fIsReady = true;
			}
		}
		
		CViewerObj.prototype.Init = function Init(urlClass, strLRNXML, strXSLPath, oLMSAPI)
		{
				m_strXSLPath = strXSLPath;	// Nastaveni cesty ke XSL
				m_ClassURL = urlClass;			
				
				if (typeof(oLMSAPI) == "object") m_oLMSAPI = oLMSAPI;
				
				mf_LoadXMLDataAsync(m_oXMLDOM, strLRNXML, this.InitRoutine);		// nacteni imsmanifest.xml
				this.m_myXMLDOM=m_oXMLDOM; // chrome nacita synchronne, takze musim znovu zverejnit
				mf_LoadXMLDataAsync(m_oXSLDOM, m_strXSLPath, this.InitRoutine);	// nacteni cpitem.xsl
				
		}

		CViewerObj.prototype.SetCurrentTOC = function SetCurrentTOC(strCurrentTOCID)
		{
			if (strCurrentTOCID) m_strCurrentTOC  = strCurrentTOCID;
		}
		
		CViewerObj.prototype.GetCurrentTOC = function GetCurrentTOC()
		{
			if (!m_oXMLDOM) return null;

			return mf_TransformFromIMStoMLT(m_strCurrentTOC, enum_SELECT_TOC);
		}

		CViewerObj.prototype.GetTOCS = function GetTOCS()
		{
			if (!m_oXMLDOM) return null;

			return mf_TransformFromIMStoMLT(null, enum_SELECT_TOCS);
		}
						
		CViewerObj.prototype.GetChildren = function GetChildren(id)
		{
			if (!m_oXMLDOM) return null;
			return mf_TransformFromIMStoMLT(id, enum_SELECT_ITEMCHILDREN);
		}
		
		CViewerObj.prototype.GetItem = function GetItem(id)
		{
			if (!m_oXMLDOM) return null;

			if (id != null)
				return mf_TransformFromIMStoMLT(id, enum_SELECT_SINGLEITEM);
		}

		CViewerObj.prototype.IsReady = function IsReady()
		{
			return m_fIsReady;
		}
		
		CViewerObj.prototype.GetCustomView = function GetCustomView()
		{
			if (!m_oXMLDOM)	return (null);
			if (!m_oXMLDOM.documentElement) return (null);

			var strURL = "";

			//check for the existance of the node that indicates a custom UI
			var node = m_oXMLDOM.selectSingleNode("//userinterface/customviewer/@href");
			
			if (null != node) strURL =  node.text;
			return strURL;
		}
		
		CViewerObj.prototype.getChildrenFromActualID = function getChildrenFromActualID(){
			return this.GetChildren(m_szCurrentNodeID);
		}
		
		//////////////////////////////////////////////////////////////////////
		//PRIVATE METHODS.
		//
		//These methods are not exposed to public references of this object.
		//////////////////////////////////////////////////////////////////////
		
		function IsIE()
		{
			return (typeof(window.ActiveXObject) != "undefined");
		}
		
		function IsOpera()
		{
			 return (typeof(window.opera) != "undefined");
		}

		function mf_CreateDOM()
		{
			var xmlDoc = null;
			
			if (IsIE())	xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");	// ActiveX pro XML DOM model
  	  else xmlDoc = document.implementation.createDocument("","",null);	// při načítání z XML souboru je nutné založit XML document /nestaci DOMPARSER /
  	  	
  	  return xmlDoc;
		}
		
		function mf_LoadXMLDataAsync(xmlDoc, xmlPath, func)
		{
			if (document.implementation && document.implementation.createDocument)
			{ 
				if (typeof(xmlDoc.load) != "undefined") 
				{	// FF, OP
					xmlDoc.onload = eval(func);
					xmlDoc.async = true;
					xmlDoc.load(xmlPath);
				} else {
					// Chrome - nema podporu XML musim pres XMLHttpRequest
					if (window.XMLHttpRequest)
					{
						xmlDoc = new window.XMLHttpRequest();
						xmlDoc.open("GET", xmlPath, false);	// synchronni
						xmlDoc.send("");
						if (xmlPath == m_strXSLPath) m_oXSLDOM = xmlDoc.responseXML;
						else m_oXMLDOM = xmlDoc.responseXML;
						eval(func());
					}
				}
			}
			else if (window.ActiveXObject)
			{
				xmlDoc.async = false;
				xmlDoc.load(xmlPath);
				eval(func());
			}
		}
	
		function mf_CreateEvent(nType,sID)
		{
			var obj = new Object();
			obj.type = nType;
			obj.id = sID;
			
			if (m_oLMSAPI) m_oLMSAPI.LRNRaiseEvent(obj);		
		}
		
		function mf_FindParent(id)
		{
			if (!m_oXMLDOM) return null;
			
			var oNode = null;
			var oParent = null;
			
			oNode = mf_FindItem(id);
			
			if (oNode) oParent = oNode.parentNode;
				
			return oParent;
		}
				
		function mf_FindItem(id)
		{
			if (!m_oXMLDOM) return null;
				
			var oNode = null;

			if (id != null) oNode = m_oXMLDOM.selectSingleNode("//item[@identifier='" + id + "']");
			
			return oNode;
		}
		
		function mf_GetItemInParentManifest(oNode)
		{
			var oParent = null;
			var szBase = oNode.getAttribute("identifier");

			while(true)
			{
				oNode = oNode.selectSingleNode("ancestor(manifestref)");
				if (oNode == null) break;
				szBase = oNode.getAttribute("identifier") + "/" + szBase;

				oParent = oNode.selectSingleNode("ancestor(manifest)/organizations//item[@resourceref='" + szBase + "']");
				if (oParent != null) break;
			}
			return oParent;
		}

		function mf_FindNext(oNode, fDescend)
		{
			if (!m_oXMLDOM) return null;
				
			var oNext = null;

			if (fDescend && (mf_ResolveTOCNodeForNext(oNode) != oNode))
				oNext = mf_ResolveTOCNodeForNext(oNode);
			else if (fDescend && oNode.firstChild != null)
				oNext =  mf_ResolveTOCNodeForNext(oNode.firstChild);
			else if (oNode.nextSibling != null)
				oNext =  mf_ResolveTOCNodeForNext(oNode.nextSibling);
			else if (oNode.parentNode.nodeName == "item")
				oNext =  mf_FindNext(oNode.parentNode, false);
			else if (oNode.parentNode.nodeName == "organization")
			{
				var oParentItem = mf_GetItemInParentManifest(oNode.parentNode);
				if (oParentItem) oNext = mf_FindNext(oParentItem, false);
			}

			if (oNext)
				if (oNext.nodeName != "item") oNext = mf_FindNext(oNext,false);

			return oNext;
		}

		function mf_ResolveTOCNodeForNext(oNode)
		{
			if (!m_oXMLDOM) return null;
				
			if (oNode.nodeName != "item") return oNode;
				
			var oResource = mf_ResourceFromItem(oNode);
		
			if (oResource == null) return oNode;
			else if (oResource.nodeName == "organization")
				return (oResource.childNodes[0]); // return the root. always an item.
			else
				return oNode;
		}
		
		function mf_FindPrevious(oNode)
		{
			if (!m_oXMLDOM)
				return (null);
			
			var oPrev = null;

			if (oNode.previousSibling != null)
			{
				oPrev = oNode.previousSibling;

				while (true)
				{
					oPrev = mf_ResolveTOCNodeForPrev(oPrev);

					if ((oPrev.nodeName == "item" || oPrev.nodeName == "organization") && oPrev.lastChild != null)
						oPrev = oPrev.lastChild;
					else
						break;
				}
			}
			else if (oNode.parentNode.nodeName == "item")
				oPrev = oNode.parentNode;
			else if (oNode.parentNode.nodeName == "organization")
			{
				var oParentItem = mf_GetItemInParentManifest(oNode.parentNode);
				if (oParentItem)
					oPrev = mf_FindPrevious(oParentItem);
			}

			if (oPrev)
			{
				if (oPrev.nodeName != "item")
					oPrev = mf_FindPrevious(oPrev);
			}

			return oPrev;
		}	
		
		
		function mf_ResolveTOCNodeForPrev(oNode)
		{
			if (!m_oXMLDOM)
				return (null);
				
			if (oNode.nodeName != "item")
				return oNode;
				
			var oResource = mf_ResourceFromItem(oNode);
		
			if (oResource == null)
				return oNode;		
			else if (oResource.nodeName == "organization")
				return oResource;
			else
				return oNode;
		}
		
		function mf_TransformFromIMStoMLT(szID, enumValueType)
		{
			var szValue = "";
			switch (enumValueType)
			{
				case enum_SELECT_SINGLEITEM:
				{
					szValue = "//item[@identifier='" + szID + "']";
					break;
				}
				case enum_SELECT_ITEMCHILDREN:
				{
					if (szID == null)
					{
						szValue = "/manifest/organizations/organization[@identifier='" + m_strCurrentTOC + "']/item";
						break;
					}

					var oNode = mf_FindItem(szID);
					var oResource = mf_ResourceFromItem(oNode);
					
					if (oResource == null) szValue = "//item[@identifier='" + szID + "']/item";
					else
					{						
						if (oResource.nodeName == "organization")
							szValue = "//organization[@identifier='" + oResource.getAttribute("identifier") + "']/item";
						else
							szValue = "//item[@identifier='" + szID + "']/item";
					}
					break;
				}	
				case  enum_SELECT_TOCS:
				{
					szValue = "/manifest/organizations//organization";
					break;
				}
				case  enum_SELECT_TOC:
				{
					szValue ="/manifest/organizations/organization[@identifier='" + szID + "']"	
					break;
				}
			}
			
			var szQuery = "//xsl:stylesheet//xsl:template//xsl:apply-templates";
			var oAppTemp = m_oXSLDOM.selectSingleNode(szQuery);
			if (oAppTemp != null) oAppTemp.setAttribute("select", szValue);
			
			var oXMLResult  =  mf_CreateDOM(); //the RESULTING XML transformation.
			
			if (IsIE()) m_oXMLDOM.transformNodeToObject(m_oXSLDOM, oXMLResult);
			else
			{
				var XSLTP = new XSLTProcessor();
				XSLTP.importStylesheet(m_oXSLDOM);
				oXMLResult = XSLTP.transformToDocument(m_oXMLDOM);
			}
			
			if( enumValueType == enum_SELECT_ITEMCHILDREN || enumValueType == enum_SELECT_SINGLEITEM) mf_SetProperties(oXMLResult);
			
			return ( oXMLResult );
		}

		function mf_SetProperties(oXML)
		{
			var nLen = oXML.documentElement.childNodes.length;
			var node = null;
			var i;
			for (i = 0; i < nLen; i++)
			{
				node = oXML.documentElement.childNodes[i];
				
				mf_SetLMSProps(node);
				mf_SetHref(node);	//temporary until new storage model.
			}	
		}	

		function mf_SetLMSProps(node)
		{
			var strStatus = "";
			
			var strPrerequisites = node.getAttribute("Prerequisites");
			if ((typeof(strPrerequisites) == "string") && (strPrerequisites != ""))
			{
				if (m_oLMSAPI)				// Currently we only support simple prerequisites
				{
					var strPrereqStatus = m_oLMSAPI.LRNGetScopedValue("cmi.core.lesson_status", strPrerequisites);
					if ((strPrereqStatus == "completed") || (strPrereqStatus == "passed")) node.setAttribute("PrerequisitesMet", "true");
					else node.setAttribute("PrerequisitesMet", "false");
				}				
			}
			else node.setAttribute("PrerequisitesMet", "true");

			if (m_oLMSAPI)
				if (node.getAttribute("DataFromLMS"))
					m_oLMSAPI.LRNSetScopedValue("cmi.launch_data", node.getAttribute("DataFromLMS"), node.getAttribute("ID"), true);
		}

		function mf_ResourceFromItem(item)
		{
			if (item == null) return null;

			var sIDRef = item.getAttribute("identifierref");

			if (sIDRef == null) return null;
			if (sIDRef == "") return null;

			// split the identifier into XPath-style notation
			var arr = sIDRef.split("/");

			var rsc = item.selectSingleNode("/manifest/resources/resource[@identifier='" + arr[i] + "']");
			if (rsc != null) return rsc;

			var rsc = item.selectSingleNode("/manifest/organizations/organization[@identifier='" + arr[i] + "']");
			return rsc;
		}
		
		function mf_SetHref(node)
		{
			var szHref = "";
			var sIDRef = "";
			var rsc;
			var szQuery;

			if (node != null)
			{
				sIDRef = node.getAttribute("ResourceRef");
				
				if (sIDRef != "")
				{
					var arr = sIDRef.split("/");
					var szQuery = "//resources/resource[@identifier = '" + arr[arr.length-1] + "']";
					rsc = m_oXMLDOM.selectSingleNode(szQuery);

					if (rsc != null)
						szHref = rsc.getAttribute("href");

					// chrismof - get parameters attribute if present
					var sID = node.getAttribute("ID");
					szQuery = "//item[@identifier = '" + sID + "']";
					rsc = m_oXMLDOM.selectSingleNode(szQuery);
					if (rsc != null && rsc.getAttribute('parameters') != "")
						szHref += "?" + rsc.getAttribute("parameters");
				}
				else
					szHref = "viewer\\blank.htm";
			}

			if (szHref != null)
				node.setAttribute("Href", szHref);
			else
				node.setAttribute("Href","viewer\\blank.htm");			
		}	
	
		function mf_EventHandler(obj)
		{
			switch(obj.type)
			{
				case LMSAPI_LESSONSTATUS:					
					mf_CreateEvent(enum_CPO_LESSONSTATUS, obj.id)
					break;
				case LMSAPI_EXITSTATUS:
					mf_CreateEvent(enum_CPO_EXITSTATUS, obj.id)
					break;
			}
		}
}




function ContentViewerEvtsObj()
{	
	var enum_CPO_INIT = 3;
	var arrListeners = new Array();
	var oLMSAPI = null;
	var nNext = 0;
	
	ContentViewerEvtsObj.prototype.Init = function Init(oAPI)
	{
		oLMSAPI = oAPI;
	}

  ContentViewerEvtsObj.prototype.ListenForEvents = function ListenForEvents(fnHandler)
  {
	  var oListener = new Object();
	  oListener.fnHandle = fnHandler;
	  arrListeners[nNext] = oListener;
	  nNext++;
	  
	  if(null != oLMSAPI)
	  {
	    if(true == oLMSAPI.LRNIsReady())
		 	{
		    var obj = new Object();
				obj.type = enum_CPO_INIT;
				obj.id = null;
				fnHandler(obj);
		  }
	  }
  }
   
  ContentViewerEvtsObj.prototype.UnListenForEvents = function UnListenForEvents(fnHandler)
  {	  
	  	for (var i =0 ; i< arrListeners.length;i++)
	  	{
	  		if (arrListeners[i])
				if (arrListeners[i].fnHandle == fnHandler) arrListeners[i] = null;
		 }
	}	
    
	//arg contains event type and data.	
  ContentViewerEvtsObj.prototype.RaiseEvent = function RaiseEvent(arg)
  {
		for (var i =0 ; i< arrListeners.length;i++)
		{
				var obj = arrListeners[i];
				if (null != obj) obj.fnHandle(arg);
		}
	}
}


// constructor
function Timer()
{
	try
	{
		this.m_datetime = new Date();
		return this;
	}
	catch(e)
	{
		return null;
	}
}

// Return Value: none
Timer.prototype.ResetTimer = function ResetTimer()
{
	try
	{
		this.m_datetime = new Date();
	}
	catch(e)
	{
	}
	return;
}

// Return Value: time delta in seconds
Timer.prototype.GetTimeDelta = function GetTimeDelta()
{
	try
	{
		return Math.round( (new Date() - this.m_datetime) / 1000 );
	}
	catch(e)
	{
		return 0;
	}
}

// Return Value: time delta in seconds
Timer.prototype.UnFormatTimeDelta = function UnFormatTimeDelta(strTime)
{
	try
	{
		if("string" != typeof(strTime))
		{
			return 0;
		}
		
		var arrTime = strTime.split(":");
		if(3 != arrTime.length)
		{
			return 0;
		}

		var nHours = parseInt(arrTime[0]);
		var nMinutes = parseInt(arrTime[1]);
		var nSeconds = parseInt(arrTime[2]);
		if(	(true == isNaN(nHours))		||
			(true == isNaN(nMinutes))	||
			(true == isNaN(nSeconds))	)
		{
			return 0;
		}

		return (nHours * 60 * 60) + (nMinutes * 60) + nSeconds;
	}
	catch(e)
	{
		return 0;
	}
}

// Return Value: time delta as string
Timer.prototype.FormatTimeDelta = function FormatTimeDelta(nSeconds)
{
	try
	{
		if(("number" != typeof(nSeconds)) || (0 > nSeconds))
		{
			return "0:00:00";
		}

		// 1 hour = 60 minutes * 60 seconds 
		var nHours = Math.floor(nSeconds / (60 * 60));
		nSeconds = nSeconds - (nHours * 60 * 60);

		var nMinutes = Math.floor(nSeconds / 60);
		nSeconds = nSeconds - (nMinutes * 60);

		var strHours = nHours.toString();

		var strMinutes;
		if(10 > nMinutes)
		{
			// single digit
			strMinutes = "0" + nMinutes.toString();
		}
		else
		{
			strMinutes = nMinutes.toString();
		}

		var strSeconds;
		if(10 > nSeconds)
		{
			// single digit
			strSeconds = "0" + nSeconds.toString();
		}
		else
		{
			strSeconds = nSeconds.toString();
		}

		return strHours + ":" + strMinutes + ":" + strSeconds;
	}
	catch(e)
	{
		return "0:00:00";
	}
}

// Return Value: new time delta as string
Timer.prototype.CalculateNewTimeDelta = function CalculateNewTimeDelta(strOldTimeDelta)
{
	try
	{
		var nTimeDelta = this.GetTimeDelta();
		this.ResetTimer();

		var nOldTimeDelta = this.UnFormatTimeDelta(strOldTimeDelta);
		var nNewTimeDelta = nTimeDelta + nOldTimeDelta;
		return this.FormatTimeDelta(nNewTimeDelta);
	}
	catch(e)
	{
		return strOldTimeDelta;
	}
}



/*
Prefix-correcting evaluate statement from http://www.faqts.com/knowledge_base/view.phtml/aid/34022/fid/119
*/

if( document.implementation.hasFeature("XPath", "3.0") ){
 XMLDocument.prototype.selectNodes = function(cXPathString, xNode){
  if (!xNode) xNode = this;

  if (xNode.documentElement) var oNSResolver = this.createNSResolver(xNode.documentElement);
  else var oNSResolver = this.createNSResolver(xNode);

  var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
  
/*
  var defaultNS = this.defaultNS;
  var aItems = this.evaluate(cXPathString, xNode,{
   normalResolver:
    this.createNSResolver(this.documentElement),
        lookupNamespaceURI : function (prefix) {
           switch (prefix) {
             case "dflt":
                return defaultNS;
             default:
                return this.normalResolver.lookupNamespaceURI(prefix);
           }
        }
      },XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);
*/

  var aResult = [];
  for( var i = 0; i < aItems.snapshotLength; i++) aResult[i] =  aItems.snapshotItem(i);

  return aResult;
 }

  Element.prototype.selectNodes = function(cXPathString)
  {
 		if(this.ownerDocument.selectNodes) return this.ownerDocument.selectNodes(cXPathString, this);
  	else
  	{
   		throw "For XML Elements Only";
  	}
 	}
 	
	XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode) 
	{ 
		if (!xNode) xNode = this;
		var xItems = this.selectNodes(cXPathString, xNode);
	
		if( xItems.length > 0 ) return xItems[0];
		else return null;
	} 
 
	Element.prototype.selectSingleNode = function(cXPathString) 
	{
		if(this.ownerDocument.selectSingleNode) 
		{ 
			return this.ownerDocument.selectSingleNode(cXPathString, this);
		} 
		else{throw "For XML Elements Only";} 
	}
 
 
 /* set the SelectionNamespaces property the same for NN or IE: */
 XMLDocument.prototype.setProperty = function(p,v){
  if(p=="SelectionNamespaces" && v.indexOf("xmlns:dflt")==0){
   this.defaultNS = v.replace(/^.*=\'(.+)\'/,"$1");
  }
 }

 XMLDocument.prototype.defaultNS;
}