/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*\
	T A L I S M A   W E B   C O L L A B O R A T I O N

	Main web collaboration class and external API

	Copyright 2008 Talisma, Inc.  All rights reserved.
\*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/


/**
 * Global varaiables and constants
 */
 
var g_theListener;
var g_bytesLimit = 1024;
var g_cookieSyncPage = "wc_cookiesync.html";
var g_currentURL = document.location.href;
var portalLink = "";
var g_wcs_path = "/NetAgent/wcext/wcisapi.dll";
var g_invalidHandle = -1;


/**
 * Server Communication Class
 * Handles all comunication with WCS
 */

function NAServerComm()
{
	var thisurl = document.location.href;
	var xend = thisurl.lastIndexOf( "/" ) + 1;
	this.m_base_url = thisurl.substring( 0, xend );
	if( document.location.port != "" )
		host_name = document.location.protocol + "//" + document.location.host + ":" + document.location.port;
	else
		host_name = document.location.protocol + "//" + document.location.host;

	//	Class methods
	this.setListener = function( listener )
	{
		g_theListener = listener;
	}
}

/**
 * Make server request
 *
 * @param url		Full URL of the request
 * @param postdata	Represents the unencoded POST body
 */
NAServerComm.prototype.sendRequest = function( url, token, postdata )
{
	// Does URL begin with http?
	if( url.substring(0, 4) != "http" )
	{
		if( url.charAt(0) == '/' )
			url = host_name + url;
		else
			url = this.m_base_url + url;
	}

	// Adjust for request token id
	var sScriptId = "__WC__SERVER__IO_" + token;
	if( url.indexOf( "?" ) >= 0 ) url += "&t=" + token;
	else url += "?t=" + token;

	// Create new JS element
	var theCommScript = document.createElement( "SCRIPT" );
	theCommScript.id = sScriptId;
	theCommScript.type = "text/javascript";
	//this.m_theCommScript.onreadystatechange = this.onReceiveResponse;
	if( postdata == null )
		theCommScript.src = url;
	else
		if( url.indexOf( "?" ) >= 0 )
			theCommScript.src = url + "&post=" + escape( postdata );
		else
			theCommScript.src = url + "?post=" + escape( postdata );

	// Append JS element (therefore executing the 'AJAX' call)
	document.body.appendChild( theCommScript );
	return true;
}

/**
 * Destroy all element event handlers
 */
function purgeElement( oElem )
{
    var oNodes = oElem.attributes;
    if( oNodes )
	{
        for( var i = 0; i < oNodes.length; i++ )
		{
            var name = oNodes[i].name;
            if( typeof oElem[name] == 'function' )
			{
                oElem[name] = null;
            }
        }
    }
    oNodes = oElem.childNodes;
    if( oNodes )
	{
        for( var i = 0; i < oNodes.length; i++ )
		{
            purge( oElem.childNodes[i] );
        }
    }
}

/**
 * Destroy communication script element
 */
function onScriptCleanup( token )
{
	var sScriptId = "__WC__SERVER__IO_" + token;
	var oScriptElem = document.getElementById( sScriptId );
	if( oScriptElem != null )
	{
		purgeElement( oScriptElem );
		document.body.removeChild( oScriptElem );
	}
}

/**
 * Recieve response
 */
function onReceiveResponse( xml_response )
{
	var oXmlResponse;
	if( window.ActiveXObject )	// IE
	{
		try
		{
			oXmlResponse = new ActiveXObject( "Microsoft.XMLDOM" );
			oXmlResponse.async = "false";
			oXmlResponse.loadXML( xml_response );
		}
		catch(e)
		{
			oXmlResponse = null;
			alert("Exception thrown trying to create Microsoft.XMLDOM :" + e.message);
			return false;
		}
	}
	else
	{
		try
		{
			var domParser = new DOMParser();
			oXmlResponse = domParser.parseFromString( xml_response,"application/xml" );
			domParser = null;
		}
		catch(e)
		{
			domParser = null;
			oXmlResponse = null;
			alert("Exception thrown trying to create DOMParser :" + e.message);
			return false;
		}
	}
	//this.m_theCallback( oXmlResponse );
	g_theListener.responseRecieved( oXmlResponse );
	oXmlResponse = null;
	return true;
}

 
/**
 * Event Recorder Class
 * Allows for simple recording of events
 * for playback later.  Used as an event clipboard
 *
 */
function EventRecorder()
{
	this.m_Recordings = new Object();
	this.recordEvent = function(recording, event)
	{
		if( this.m_Recordings[recording] == null )
			this.m_Recordings[recording] = new Array();
		this.m_Recordings[recording].push(event);
	}
	this.playbackEvents = function(recording, callback)
	{
		if( this.m_Recordings[recording] != null )
		{
			while( this.m_Recordings[recording].length > 0 )
				callback( this.m_Recordings[recording].shift() );
		}
	}
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	G E N E R A L   A P I
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

// XML Functions
function XML_QueryNode( doc, tagname )
{
	try
	{
		return doc.getElementsByTagName(tagname)[0];
	}
	catch(e)
	{
		return null;
	}
}

function XML_GetNodeText( node )
{
	try
	{
		if( node != null && node.firstChild != null )
			return node.firstChild.nodeValue;
		else
			return "";
	}
	catch(e)
	{
		return "";
	}

}

function XML_QueryNodeText( doc, tagname )
{
	try
	{
		return XML_GetNodeText( doc.getElementsByTagName(tagname)[0] );
	}
	catch(e)
	{
		return "";
	}
}

function XML_GetNodeAttribute( node, name )
{
	try
	{
		var attr = node.attributes.getNamedItem( name );
		if( attr == null ) return "";
		else return attr.nodeValue;
	}
	catch(e)
	{
		return "";
	}
}

function XML_SetNodeAttribute( node, name, value )
{
	try
	{
		var attr = node.attributes.getNamedItem( name );
		if( attr != null )
		{
			attr.nodeValue = value;
		}
	}
	catch(e){}
}

//////////////////////////////////////////////
// Input disabling functions

function DisableInputElement(oInputElem)
{
	switch(oInputElem.tagName.toLowerCase())
	{
	case "input":
		switch(oInputElem.type.toLowerCase())
		{
		case "radio": oInputElem.disabled = true; break;
		case "checkbox": oInputElem.disabled = true; break;
		default: oInputElem.readOnly = true; break;
		}
		break;

	case "textarea":
		oInputElem.readOnly = true;
		break;

	case "select":
		oInputElem.disabled = true;
		break;
	}
}

function DisableAllInputElements()
{
	try
	{
		var oInputs = document.getElementsByTagName("INPUT");
		for( var i = 0; i < oInputs.length; i++ )
			DisableInputElement(oInputs[i]);
		
		var oTextAreas = document.getElementsByTagName("TEXTAREA");
		for( var i = 0; i < oTextAreas.length; i++ )
			DisableInputElement(oTextAreas[i]);
		
		var oSelects = document.getElementsByTagName("SELECT");
		for( var i = 0; i < oSelects.length; i++ )
			DisableInputElement(oSelects[i]);
	}
	catch(e){}
}

function DisableInputElementByName(name)
{
	try
	{
		var oElems = document.getElementsByName(name);
		for( var i = 0; i < oElems.length; i++ )
			DisableInputElement(oElems[i]);
	}
	catch(e){}
}

///////////////////////////////////////////////
///////////////////////////////////////////////

function AttachToEvent( obj, evType, callback )
{
	if( obj.addEventListener )
	{
		obj.addEventListener( evType, callback, false );
		return true;
	}
	else if( obj.attachEvent )
	{
		return obj.attachEvent( "on" + evType, callback );
	}
	return false;
}

function RandomNum()
{
	return ( Math.floor( Math.random() * (1000000) ) );
}

function CheckWCResponse(stopVal)
{
	try
	{
		if(TALCOB)
		{
			if(portalLink == "")
			{
				window.setTimeout("CheckWCResponse(1)", 1200);
			}	
			if(portalLink == "" && stopVal == 1)
			{
				if (this.OnWCSessionStartedCallback != null)
				{
					var wcParam = "&wcs=";
					this.OnWCSessionStartedCallback(wcParam);
				}
				else if( window.OnWCSessionStarted != null )
					if( OnWCSessionStarted() == false )
						return;
			}
		}
	}
	catch(e)
	{
		return;
	}
}

// This function decodes the any string
// that's been encoded using URL encoding technique
function URLDecode(psEncodeString)
{
	// Create a regular expression to search all +s in the string
	var lsRegExp = /\+/g;
	// Return the decoded string
	return unescape(String(psEncodeString).replace(lsRegExp, " "));
}

function DoesURLContainWCS( sURL )
{
	var i = sURL.indexOf( "wcs=" );
	if( i >= 0 )
	{
		return true;
	}
	return false;
}

function ParseWCS( wcs )
{
	var id, host;
	if( wcs != null && wcs != "null" )
	{
		var iDelim = wcs.indexOf( "@" );
		if( iDelim >= 0 )
		{
			id = wcs.substr( 0, iDelim );
			host = wcs.substr( iDelim + 1 );
		}
		else
		{
			id = wcs;
		}
	}
	return{ id:id, host:host };
}

function GetParam( sName )
{
	var sSearch = window.location.search;
	sSearch = sSearch.substr( 1, sSearch.length-1 );
	var aParams = sSearch.split( "&" );
	for( var i = 0; i < aParams.length; i++ )
	{
		var aParam = aParams[i].split( "=" );
		if( sName == aParam[0] )
		return decodeURI( aParam[1] );
	}
	return null;
}

function GetCookie( sName )
{
	// Cookies are separated by semicolons
	var aCookie = document.cookie.split( "; " );
	for( var i = 0; i < aCookie.length; i++ )
	{
		// A name/value pair (a crumb) is separated by an equal sign
		var crumbName, crumbValue;
		var iDelim = aCookie[i].indexOf( "=" );
		if( iDelim >= 0 )
		{
			crumbName = aCookie[i].substr( 0, iDelim );
			if( crumbName == sName )
			{
				crumbValue = aCookie[i].substr( iDelim + 1 );
				return decodeURI( crumbValue );
			}
		}
	}

	// A cookie with the requested name does not exist
	return null;
}

function SetCookie( sName, sValue )
{
	// Set session cookie for domain at root level
	var sNewCookie;
	if( window.ActiveXObject )	// IE
	{
		// Extract only the domain from the host name
		var hostname = document.domain.split(".");
		var domainname = hostname[hostname.length-2] + "." + hostname[hostname.length-1];
	    if (typeof(talCookPath) != "undefined")
	        sNewCookie = sName + "=" + encodeURI(sValue) + "; path=" + talCookPath + "; domain=" + domainname;
	    else
		    sNewCookie = sName + "=" + encodeURI(sValue) + "; path=/; domain=" + domainname;
	}
	else if(navigator.userAgent.toLowerCase().indexOf("safari")>-1)
		sNewCookie = sName + "=" + encodeURI(sValue) + ";";
	else
		sNewCookie = sName + "=" + encodeURI(sValue) + "; path=\"/\"";
	document.cookie = sNewCookie;
}

// Delete the cookie with the specified name.
function DelCookie( sName )
{
	//alert("deleting cookie..." + sName );
	document.cookie = sName + "=null; expires=Fri, 31 Dec 1999 23:59:59 GMT;";
	if( GetCookie(sName) != null )
	{
		// Set cookies to 'null' since it failed to delete
		SetCookie( sName, "null" );
	}
}

/**
 * Iterates all cookies and deletes them.
 */
function deleteAllCookies()
{
	// Cookies are separated by semicolons
	var aCookie = document.cookie.split( "; " );
	for( var i = 0; i < aCookie.length; i++ )
	{
		// A name/value pair (a crumb) is separated by an equal sign
		var crumbName, crumbValue;
		var iDelim = aCookie[i].indexOf( "=" );
		if( iDelim >= 0 )
		{
			crumbName = aCookie[i].substr( 0, iDelim );
			var name = crumbName.toLowerCase();
			if(name == "netagent_properties" || name == "is_authenticated" || name == "netagent_permissions" || name == "databaseid" || name == "is_agent" || name == "wcs") continue;
			//if(name.indexOf("aspsessionid") > -1 || name.indexOf("asp.net_sessionid") > -1) continue;
			if( GetCookie(crumbName) != null )
			{
				// Set cookies to 'null' since it failed to delete
				SetCookie( crumbName, "null" );
			}
		}
	}
}

function ExtractDomainFromURL( sURL )
{
	var urlcomp = CrackUrl( sURL );
	var sHost = urlcomp.host;
	if( IsIPAddr( sHost ) == false )
	{
		var iDot = sHost.indexOf( "." );
		if( iDot >= 0 )
		{
			return sHost.substr( iDot + 1 );
		}
	}
	return sHost;
}

function IsIPAddr( sHost )
{
	var exp = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i;
    if( sHost.match(exp) )
		return true;
    else
        return false;
}

function CrackUrl( sURL )
{
	var exp = /^(http[s]?|ftp):\/?\/?([^:\/\s]+):*(\d*)((?:\/[\w\-\%\:\+]+)*\/)*([\w-\.]+[^#?\s]+)?(.*)$/i;
    if( sURL.match(exp) )
	{
		return{ url: RegExp['$&'],
				 protocol: RegExp.$1,
				 host:RegExp.$2,
				 port:RegExp.$3,
				 path:RegExp.$4,
				 file:RegExp.$5,
				 query:RegExp.$6 };
    }
    else
	{
        return{ url:"", protocol:"", host:"", port:"", path:"", file:"", query:"" };
    }
}

function Enum()
{
	for( var i = 0; i < arguments.length; i++ )
		if( typeof(window[arguments[i].toString()]) == "undefined" )
			window[arguments[i].toString()] = i;
}

function SetGlobalCursor(cursor)
{
	for( var i = 0; i < document.all.length; i++ )
	{
		var obj = document.all[i];
		if( obj.style )
			obj.style.cursor = cursor;
	}
}

function SetDisplayText(text)
{
	var modeDisplay = document.getElementById( "WC_MODE" );
	if( modeDisplay != null )
		modeDisplay.innerText = text + " : " + g_theWCObj.m_frameIdx;
}

function getClientHeight()
{
	if(window.innerHeight!=window.undefined) return window.innerHeight;
	if(document.compatMode=='CSS1Compat') return document.documentElement.clientHeight;
	if(document.body) return document.body.clientHeight;
	return window.undefined;
}

function getClientWidth()
{
	if(window.innerWidth!=window.undefined) return window.innerWidth;
	if(document.compatMode=='CSS1Compat') return document.documentElement.clientWidth;
	if(document.body) return document.body.clientWidth;
	return window.undefined;
}

function MakeLinkAbsolute( sURL )
{
	// Check for postback senario
	if( sURL.length == 0 )
	{
		var sTmp = document.location.href.toLowerCase();
		if( sTmp.indexOf( "wcisapi.dll" ) >= 0 )	// Proxy URL - Take location from query string
			sURL = GetParam( "url" );
		else
			sURL = document.location.href;
	}

	// Check to see if the URL is complete
	if( sURL.indexOf( "://" ) < 0 )
	{
		// Find the base URL of the page
		var baseURL = "";
		var baseTag = document.getElementsByTagName( "BASE" );
		if( baseTag[0] != null )
			baseURL = baseTag[0].href;
		else
			baseURL = document.location.href;

		// Crack url into parts
		var oURL = CrackUrl( baseURL );
		var sFullHost = oURL.host;
		if( oURL.port.length > 0 ) sFullHost += ":" + oURL.port;

		// Complete URL
		if( sURL.charAt( 0 ) == '/' )
		{
			sURL = oURL.protocol + "://" + sFullHost + sURL;
		}
		else
		{
			// Brute force logic...
			var firstCharSlash = (oURL.path.charAt(0)=='/');
			var lastCharSlash = (oURL.path.charAt(oURL.path.length-1)=='/');
			if( firstCharSlash == true && lastCharSlash == true )
				sURL = oURL.protocol + "://" + sFullHost + oURL.path + sURL;
			else if( firstCharSlash == true && lastCharSlash == false )
				sURL = oURL.protocol + "://" + sFullHost + oURL.path + "/" + sURL;
			else if( firstCharSlash == false && lastCharSlash == true )
				sURL = oURL.protocol + "://" + sFullHost + "/" + oURL.path + sURL;
			else// if( firstCharSlash == false && lastCharSlash == false )
				sURL = oURL.protocol + "://" + sFullHost + "/" + oURL.path + "/" + sURL;
		}
	}
	return sURL;
}

function MakePostRequest( action, data )
{
	var oForm = document.createElement( "FORM" );
	oForm.action = action;
	oForm.method = "POST";
	document.body.appendChild( oForm );
	var aInputs = data.split( "&" );
	for( var i = 0; i < aInputs.length; i++ )
	{
		var aInput = aInputs[i].split( "=" );
		var oInput = document.createElement( "INPUT" );
		oInput.type = "hidden";
		oInput.name = aInput[0];
		oInput.value = URLDecode( aInput[1] );
		//alert( URLDecode(aInput[1]) );
		oForm.appendChild( oInput );
	}
	oForm.submit();
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	G L O B A L   E N U M S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

// Web Collaboration UI Mode
Enum("NORMAL","POINTER");

// Web Collaboration client types
Enum("CUSTOMER","AGENT","UNKNOWN");

Enum("PUBLIC","PRIVATE");


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	M A I N   O B J E C T
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Main Web Collaboration Class
 * Business logic for WC client
 *
 */
function NAWebCollab()
{
	this.m_UITags = new Array("INPUT","SELECT","TEXTAREA");
	this.m_theServer;
	this.m_theParams = new Object();		// TODO: This array should contain objects instead of strings in the future
	this.m_paramStatus = new Object();		// TODO: This array should be removed and replaced with a property in the above mentioned objects
	this.m_responseQueue = new Array();	// Store server responses in a queue to be handled by a worker thread
	this.m_theInterval = g_invalidHandle;
	this.m_clientTimeout = 10;				// Client timeout setting
	this.m_lastResponse;
	this.m_thePtr;
	this.m_theDebugDisp;
	this.m_theFocusName;
	this.m_frameIdx = 0;					// Frame index
	this.m_theHost;							// Remote host
	this.m_theSessId;						// Session Id
	this.m_sesActive = false;				// Current session status
	this.m_uiMode = NORMAL;				// Current ui mode
	this.m_clientType = CUSTOMER;			// Client type
	this.m_selectedObj;						// Currently selected pointer obect
	this.m_locationCount = 0;				// Location count (used to detect postbacks)
	this.m_lastStyle_BACKGROUNDCOLOR;
	this.m_lastStyle_CURSOR;
	this.m_lastStyle_BORDERWIDTH;
	this.m_lastStyle_BORDERCOLOR;
	this.m_hltStart;						// Highlighting start location
	this.m_hltEnd;							// Highlighting end location
	this.m_hltColor = "yellow";			// Highlighting color
	this.m_dbgLog = new Array();
	this.m_dbgLastResponse = "";
	this.m_dbgLoggingEnabled = true;
	this.m_events = new EventRecorder();	// Used to record events and allow for rollback

	// Determine wcs host by using the script src
	var oScripts = document.getElementsByTagName("SCRIPT");
	for( var i = 0; oScripts.length; i++ )
	{
		var oScript = oScripts[i];
		if( oScript.src.indexOf("wc.js") >= 0 )
		{
			var URL = CrackUrl(oScript.src);
			if( URL.port.length > 0 )
				this.m_theHost = URL.protocol + "://" + URL.host + ":" + URL.port;
			else
				this.m_theHost = URL.protocol + "://" + URL.host;
			break;
		}
	}
	
	this.getClientId = function()
	{
		var iDelim = this.m_theSessId.indexOf(":");
		if( iDelim >= 0 )
		{
			return this.m_theSessId.substr( iDelim + 1 );
		}
		return "";
	}

	this.posLeft = function( elmt )
	{
		var l = 0;
		while( elmt.offsetParent != null )
		{
			l += elmt.offsetLeft;
			elmt = elmt.offsetParent;
		}
		return l;
	}

	this.posTop = function( elmt )
	{
		var t = 0;
		while( elmt.offsetParent != null )
		{
			t += elmt.offsetTop;
			elmt = elmt.offsetParent;
		}
		return t;
	}

	this.OnWCSessionStartedCallback = null;
}

/**
 * Callback function to handle incoming data
 *
 * @param xml_doc	xml dom representing server response
 */
NAWebCollab.prototype.responseRecieved = function( xml_doc )
{
	// Push response xml onto queue
	this.m_responseQueue.push(xml_doc);
	
	// Fire event to process server response
	window.setTimeout("g_theWCObj.processResponse();", 10);
}

/**
 * Callback function to handle incoming data
 *
 * @param xml_doc	xml dom representing server response
 */
NAWebCollab.prototype.processResponse = function()
{
	// Get first xml response from response queue
	var xml_doc = this.m_responseQueue.shift();

	// Reset interval timeout
	this.resetIntervalTimeout();

	// Process response
	this.m_dbgLastResponse = xml_doc.xml;
	var response_node = XML_QueryNode(xml_doc,"response");
	if( response_node == null ) return;
	var type = XML_GetNodeAttribute(response_node,"type");
	switch( type )
	{
	case "action":
		this.processAction( xml_doc );
		break;

	case "error":
		
		// Log error
		var msg = XML_QueryNodeText(xml_doc,"msg");
		if( msg != null )
		{
			this.debugLogWrite(msg);
		}
		
		this.debugLogWrite("Server error recieved - session shutdown started");

		// Shutdown session
		this.shutdownSession();
		
		// Write session end message to log
		this.debugLogWrite("Session ended!");

		if(this.m_theSessId == null || this.m_theSessId == 'undefined')
		{
			if (this.OnWCSessionStartedCallback != null)
			{
				var wcParam = "&wcs=";
				this.OnWCSessionStartedCallback(wcParam);
			}
			else if( window.OnWCSessionStarted != null )
				if( OnWCSessionStarted() == false )
					return;
		}
		break;

	case "ack":
		// Do nothing with this response for now
		break;
	}

	// Fire event to clean script element
	var tok = XML_GetNodeAttribute(response_node,"tok");
	window.setTimeout("onScriptCleanup('" + tok + "');", 1000);
	
	xml_doc = null;
	response_node = null;
}

/**
 * Callback function to handle incoming data
 *
 * @param xml_doc	xml dom representing server response
 */
NAWebCollab.prototype.processAction = function( xml_doc )
{
	var response_node = XML_QueryNode(xml_doc,"response");
	if( response_node == null ) return;
	var cmd = XML_GetNodeAttribute(response_node,"cmd");
	switch( cmd )
	{
	case "init":
		var sessId = XML_QueryNodeText(xml_doc,"id");
		var clientId = XML_QueryNodeText(xml_doc,"cid");
		if( sessId != null && clientId != null )
		{
			// Retrieve id and make callback
			var hostName = XML_QueryNodeText(xml_doc,"host");
			SetCookie( "WCS", sessId + ":" + clientId + "@" + hostName );
			this.m_theSessId = sessId + ":" + clientId;
			//this.m_theClientId = clientId;
			if (this.OnWCSessionStartedCallback != null)
			{
				var wcParam = "&wcs=" + escape(sessId + "@" + this.m_theHost)
				this.OnWCSessionStartedCallback(wcParam);
			}
			else if( window.OnWCSessionStarted != null )
				if( OnWCSessionStarted( sessId ) == false )
					return;

			// Start web collab session
			this.startSession();

			// We must handle the senario where the session is initiated from
			// a frame within a frameset.
			if( parent != self )
			{
				// Propagate this call - special case since the initial call might
				// be in any frame of a frameset unlike all external calls which
				// always start from the top frame
				eval("window.top.g_theWCObj.initSession()");
				this.propagateMethodCall( window.top, "g_theWCObj.initSession();" );
			}
		}
		else
		{
			this.debugLogWrite("Invalid init response");
		}
		break;

	case "settings":
		// Import settings from server
		var ptrImg = XML_QueryNodeText(xml_doc,"ptr-img");
		if( ptrImg != null && ptrImg != "null" )
		{
			// If a relative path is supplied - point it to the session server
			var linkPtrImg;
			if( ptrImg.charAt(0) == '/' )
				linkPtrImg = this.m_theHost + ptrImg;
			else
				linkPtrImg = ptrImg;
				
			// Set pointer image
			var oPtr = document.getElementById("WC_PTR");
			oPtr.innerHTML = "<img src='" + linkPtrImg + "'/>";
		}
		var hltColor = XML_QueryNodeText(xml_doc,"hlt-color");
		if( hltColor != null )
		{
			this.m_hltColor = hltColor;
		}
		var pushFrm = XML_QueryNodeText(xml_doc,"push-frame");
		if( pushFrm != null )
		{
			// Set this frame as the push frame for the client
			window.name = "PushFrame";
		}

		// Re-write post forms on the page to point to the proxy
		this.rewritePOSTs( this.m_theSessId );

		// Push current location to server
		this.pushLocation();
		break;

	case "cookies":
		if( this.m_clientType != CUSTOMER )
		{
			// Read and update cookies
			var cookies = xml_doc.getElementsByTagName("cookie");
			for( var i = 0; i < cookies.length; i++ )
			{
				var cookie = cookies[i];
				var sName = XML_GetNodeAttribute(cookie,"name");
				var sValue = unescape(XML_GetNodeText(cookie));
				if( sName.toUpperCase() != "WCS" )
					SetCookie(sName, decodeURIComponent(sValue));
			}
		}
		break;

	case "nav":
		// Retrieve client type
		var client_type = XML_QueryNodeText(xml_doc,"client-type");
		if( client_type == "CUSTOMER" )
			this.m_clientType = CUSTOMER;
		else
			this.m_clientType = AGENT;
				
		// Read the policies associated with this page
		var policies = xml_doc.getElementsByTagName("policy");
		this.debugLogWrite(xml_doc.xml);
		for( var i = 0; i < policies.length; i++ )
		{
			var policy = policies[i];
			var sStatus = XML_GetNodeAttribute(policy,"status");
			if( sStatus != "false" )	// Don't execute disables policies
				this.processPolicy( policy );
		}

		// Iterate parameters and update the values
		this.updateInputs( xml_doc );
		this.startSessionPolling();
		break;

	case "query":
		// Read the location count and initialize the local variable
		var locationCount = parseInt(XML_QueryNodeText(xml_doc,"loc-count"));
		if( this.m_locationCount == 0 ) this.m_locationCount = locationCount;

		// Read the context data from the session
		var new_url = XML_QueryNodeText(xml_doc,"url");//.toLowerCase();
		var update_client = XML_QueryNodeText(xml_doc,"update-client");
		var sClientId = this.getClientId();
		var current_url;// = document.location.href;

		// Extract actual URL from current location
		var sTmp = document.location.href.toLowerCase();
		if( sTmp.indexOf( "wcisapi.dll" ) >= 0 )	// Proxy URL - Take location from query string
			current_url = GetParam( "url" );//.toLowerCase();
		else
			current_url = document.location.href;

		// Determine the status of the session
		var session_status = XML_QueryNodeText(xml_doc,"status");
		if( session_status != "active" )
		{
			// Session has become inactive - stop processing updates
			this.m_sesActive = false;
			return;
		}

		// Check to see if the url or the location index has changed
		// The use of the location index is due to postbacks and
		// the inability to view post data of the current location
		if( ( update_client != sClientId ) &&								// Eliminate echo
			( new_url.length > 0 &&
			  ( new_url != current_url/* ||
			  this.m_locationCount != locationCount*/ ) ) )
		{
			// If this is a cache URL then re-write it
			if( new_url.indexOf("_cache://") == 0 )
			{
				// Must be a cache location - this must be prefixed client-side
				new_url = this.m_theHost + g_wcs_path + "?cmd=www&ses=" + this.m_theSessId + "&frm=" + this.m_frameIdx + "&url=" + new_url
			}
			
			// Make apropriate request
			var post_data = XML_QueryNodeText(xml_doc,"post");
			if( post_data.length == 0 )
			{
				// Perform standard HTTP GET request
				document.location.href = new_url;
			}
			else
			{
				// Perform HTTP POST request with session supplied data
				MakePostRequest( new_url, unescape(post_data) );
			}
		}
		else
		{
			// Publish cookies if the status just changed
			if( this.m_sesActive == false )
			{
				this.m_sesActive = true;
				this.publishCookies();
			}

			// Update pointer position
			var ptr = XML_QueryNode(xml_doc,"pointer");
			if( ptr != null )
			{
				var vname = XML_GetNodeAttribute(ptr,"in");
				if( this.m_theFocusName != vname )
				{
					var vins = document.getElementsByName(vname);
					if( vins.length > 0 )
					{
						var vin = vins[0];
						vin.scrollIntoView( false );
						this.m_thePtr.style.visibility = "visible";
						this.m_thePtr.style.left = this.posLeft(vin) - 50;
						this.m_thePtr.style.top = this.posTop(vin) - 10;
					}
					else
					{
						this.m_thePtr.style.visibility = "hidden";
					}
					this.m_theFocusName = vname;
				}
			}
			
			// Update highlighter position
			var hlt = XML_QueryNode(xml_doc,"highlighter");
			if( hlt != null )
			{
				//if( this.m_uiMode != HIGHTLIGHT )
				//{
					//var hlt = hlts[0];
					var vstart = XML_GetNodeAttribute(hlt,"start");
					var vend = XML_GetNodeAttribute(hlt,"end");
					if( vstart != this.m_hltStart && vend != this.m_hltEnd )
					{
						this.m_hltStart = vstart;
						this.m_hltEnd = vend;
						this.createSelection( vstart, vend );
						//var range = document.body.createTextRange();
						//range.collapse();
						//range.moveStart( "character", vstart );
						//range.moveEnd( "character", vend-vstart );
						//range.select();
						//this.highlightSelection( range );
					}
				//}
			}
			
			// Iterate parameters and update the values
			this.updateInputs( xml_doc );
		}
		break;
	}
	response_node = null;
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	P O L I C I E S   R O U T I N E S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Procedure to handle incoming policies
 *
 * @param xml_doc	xml dom representing server response
 */
NAWebCollab.prototype.processPolicy = function( policy_node )
{
	var oExps = policy_node.getElementsByTagName("expr");
	for( var i = 0; i < oExps.length; i++ )
	{
		var oExp = oExps[i];
		var sObj = XML_GetNodeAttribute(oExp,"object");
		var params = new Object();
		switch(sObj)
		{
		case "input":
			params["name"] = XML_GetNodeAttribute(oExp,"value");
			var sAction = XML_GetNodeAttribute(oExp,"action");
			if(sAction == "block")
			{
				this.businessService_Block(params);
				this.businessService_ReadOnly(params);
			}
			else if(sAction == "readonly")
				this.businessService_ReadOnly(params);
			break;

		case "link":
			params["type"] = XML_GetNodeAttribute(oExp,"value");
			this.businessService_RewriteLink(params);
			break;

		case "form":
			params["name"] = XML_GetNodeAttribute(oExp,"value");
			this.businessService_BlockForm(params);
			break;
		}
		params = null;
	}
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	B U S I N E S S   S E R V I C E S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Blocks the input element from being shared
 */
NAWebCollab.prototype.businessService_Block = function( params )
{
	// Get input name
	var sName = params["name"];
	// Add to status hash as blocked prameter
	this.m_paramStatus[sName] = PRIVATE;
}

/**
 * Blocks the form submit for agent
 */
NAWebCollab.prototype.businessService_BlockForm = function( params )
{
	if(this.m_clientType == CUSTOMER)
		return;
	
	if(params["name"] == "*")
	{
		var elems=document.getElementsByTagName("form");
		for(var i=0; i< elems.length; i++)
		{
			elems[i].action = "javascript:window.focus()";
			elems[i].submit = function()
			{
				alert('You are not authorized to submit this form.');
				this.action = "javascript:window.focus()";
			};
			elems[i].onsubmit = function()
			{
				alert('You are not authorized to submit this form.');
				return false;
			};
		}
	}
	else
	{
		var elemz=document.getElementsByTagName("form");
		for(var j=0; j< elemz.length; j++)
		{
			if(elemz[j].name == params["name"])
			{
				elemz[j].action = "javascript:window.focus()";
				elemz[j].submit = function()
				{
					alert('You are not authorized to submit this form.');
					this.action = "javascript:window.focus()";
				};
				elemz[j].onsubmit = function()
				{
					alert('You are not authorized to submit this form.');
					return false;
				};
			}
		}
	}
	return;
}

/**
 * Sets input element to readonly
 */
NAWebCollab.prototype.businessService_ReadOnly = function( params )
{
	if( this.m_clientType == CUSTOMER ) return;

	// Get input name
	var sName = params["name"];
	if( sName == "*" ) DisableAllInputElements();
	else DisableInputElementByName( sName );
}

/**
 * Rewites links in order to force them through the proxy server
 * this allows the resulting pages to match even if the actual
 * web server changes thing randomly or through rotation. Only
 * one request is made, the other is just a copy.
 */
NAWebCollab.prototype.businessService_RewriteLink = function( params )
{
	// Get input name
	var sType = params["type"];

	// TODO: add more type of links to prefix
	switch(sType)
	{
	case "any":
	//	this.rewriteGETs();
	//	this.rewriteAnchors();
		//this.rewriteImages();
		this.debugLogWrite("Use of depreciated policy (type-any-rewrite)");
		break;

	case "form":
	//	this.rewriteGETs();
		this.debugLogWrite("Use of depreciated policy (type-form-rewrite)");
		break;

	case "anchor":
		this.rewriteAnchors();
		break;
	}
}
		
		
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	S E R V E R   R E Q U E S T S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Joins a session
 */
NAWebCollab.prototype.joinSession = function(session, host)
{
	// Join a existing session
	this.m_theSessId = session;
	this.m_theHost = host;
	if(this.m_theServer)
		this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=join&ses=" + this.m_theSessId, RandomNum() );
}

/**
 * Set session status to active/inactive
 */
NAWebCollab.prototype.activateSession = function( active )
{
	var sStatus = "";
	if( active == true )
	{
		sStatus = "active";
	}
	else
	{
		sStatus = "inactive";
		this.deleteCookies();
	}
		
	// Send session activation request
	if(this.m_theServer)
		this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=status&ses=" + this.m_theSessId + "&status=" + sStatus, RandomNum() );

	// Make identical call to all children frames
	this.makeMethodCall("g_theWCObj.activateSession(" + active + ");");
}

/**
 * Request settings
 */
NAWebCollab.prototype.requestSettings = function()
{
	// Send settings request
	if(this.m_theServer)
		this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=settings&ses=" + this.m_theSessId, RandomNum() );
}

/**
 * Push current location
 */
NAWebCollab.prototype.pushLocation = function()
{
	// Extract actual URL from current location
	var sFromCache;
	var sTmp = document.location.href.toLowerCase();
	if( sTmp.indexOf( "wcisapi.dll" ) >= 0 )	// Proxy URL - Take location from query string
	{
		sURL = GetParam( "url" );
		sFromCache = "1";
	}
	else
	{
		sURL = document.location.href;
		sFromCache = "0";
	}

	// Send navigation request
	if(this.m_theServer)
		this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=nav&ses=" + this.m_theSessId + "&frm=" + this.m_frameIdx + "&fc=" + sFromCache + "&url=" + escape(sURL), RandomNum() );
}

/**
 * Shutdown session
 */
NAWebCollab.prototype.shutdownSession = function()
{
	//---------------------------------------------
	// 		S H U T D O W N   S E S S I O N
	//---------------------------------------------
	// Error from server : Session must be shutdown
	//---------------------------------------------
	if( this.stopSessionPolling() )
	{
		this.debugLogWrite("Session shutting down...");

		// Delete all cookies on agent side / session cookie on customer side
		if( this.m_clientType == AGENT )
			this.deleteCookies();
		else
			DelCookie( "WCS" );

		// Hide the pointer
		if( this.m_thePtr != null )
			this.m_thePtr.style.visibility = "hidden";		// Hide pointer
			
		// Undo form rewrites
		this.debugLogWrite("Undo form rewrites...");
		this.m_events.playbackEvents("form_proxy_rewrite", this.undoForms);

		// Undo anchor rewrites
		this.debugLogWrite("Undo anchor rewrites...");
		this.m_events.playbackEvents("anchor_proxy_rewrite", this.undoAnchors);
		
		this.debugLogWrite("Session shutdown!");
	}
	//---------------------------------------------
	//---------------------------------------------
}

/**
 * Exits session
 */
NAWebCollab.prototype.exitSession = function()
{
	// Stop polling session
	this.stopSessionPolling();
	
	// Clear all cookies for session
	this.deleteCookies();
	
	// Make identical call to all children frames
	this.makeMethodCall("g_theWCObj.exitSession();");
}

/**
 * Closes session
 */
NAWebCollab.prototype.closeSession = function()
{
	// Send session close request
	this.exitSession();
	if(this.m_theServer)
		this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=close&ses=" + this.m_theSessId, RandomNum() );
}

/**
 * Publish input parameters
 */
NAWebCollab.prototype.publishParameters = function( paramXML )
{
	if(this.m_theServer)
		this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=publish&ses=" + this.m_theSessId + "&frm=" + this.m_frameIdx, RandomNum(), "<parameters>" + paramXML + "</parameters>" );
}

/**
 * Reset Interval Timeout
 */
NAWebCollab.prototype.resetIntervalTimeout = function()
{
	this.m_lastResponse = new Date().getTime();
}

/**
 * Verify Interval Timeout
 */
NAWebCollab.prototype.verifyIntervalTimeout = function(msTimeout)
{
	if( (this.m_lastResponse+msTimeout) < new Date().getTime() )
	{
		return true;
	}
	return false;
}

/**
 * Iterates all input elements on the page and publishes any values which have
 * changes since the last publication.
 */
NAWebCollab.prototype.pollSession = function()
{
	if( this.m_theSessId != null )
	{
		if( this.verifyIntervalTimeout(this.m_clientTimeout*1000) == false )
		{
			// If the session is active - publish inputs
			if( this.m_sesActive == true )
				this.publishInputs();
			
			// Make request for updates
			if(this.m_theServer)
				this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=query&ses=" + this.m_theSessId + "&frm=" + this.m_frameIdx, RandomNum() );

			return;
		}
		else
		{
			this.debugLogWrite("Server timeout - session shutdown started");
		}
	}
	else
	{
		this.debugLogWrite("Invalid session id or server timeout - session shutdown started");
	}
		
	// Shutdown session
	this.shutdownSession();
	
	this.debugLogWrite("Session shutdown complete");
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	F R A M E   H A N D L I N G   R O U T I N E S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Iterates all frames recursively and counts them
 * to produce a frame index
 *
 * @param frame		Frame to start recursing
 */
NAWebCollab.prototype.walkFrames = function( frame )
{
	for( var i = 0; i < frame.frames.length; i++ )
	{
		this.m_frameIdx++;
		
		var oFrame = frame.frames[i];
		if( oFrame == self )
		{
			return true;
		}
		else if( oFrame.frames.length > 0 )
		{
			if( this.walkFrames( oFrame ) )
			{
				return true;
			}
		}
	}
	return false;
}

/**
 * Determine the frame index of the current frame
 */
NAWebCollab.prototype.setFrameIndex = function()
{
	if( parent != self )
	{
		if( this.walkFrames( window.top ) == false )
			this.m_frameIdx = -1;
	}
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	I N I T I A L I Z A T I O N   R O U T I N E S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Initiate web collaboration session from a proxied page
 *
 * @param id	Web Collaboration session id
 */
NAWebCollab.prototype.initFromProxiedPage = function( id, host, cookiesyncpath )
{
	if( id.length == 0 ) return;

	// Verify that a cookiessync path has been determined before actually creating
	// the iframe element
	if( cookiesyncpath.length > 0 )
	{
		// Search for META REFRESH disabled by the proxy so it can be executed by cookiesync
		var sMeta = "";
		var oMetas = document.getElementsByTagName("META");
		for( var i = 0; i < oMetas.length; i++ )
		{
			var oMeta = oMetas[i];
			var sMetaName = oMeta.name;
			if( sMetaName == "WC_META_REFRESH" )
			{
				var sWaitTime = "", sUrl;
				var sMetaContent = oMeta.content;
				var iDelim = sMetaContent.indexOf( ";" );
				if( iDelim >= 0 )
				{
					sWaitTime = sMetaContent.substr( 0, iDelim ) + ";";
					sUrl = sMetaContent.substr( iDelim + 1 );
				}
				else
				{
					sUrl = sMetaContent;
				}
				sMeta = "&meta=" + sWaitTime + sUrl;
				break;
			}
		}
		// /////////////////////////////////////////////

		// Generate iframe to pass cookies from this domain back to the original domain
		var theFrm				= document.createElement( "IFRAME" );
		theFrm.id 				= "WC_IFRAME";
		theFrm.src				= cookiesyncpath + "?wcs=" + id + "@" + host + sMeta;
		theFrm.style.position 	= "absolute";
		theFrm.style.visibility	= "hidden";
		theFrm.style.top 		= "0px";
		theFrm.style.left 		= "0px";
		document.body.appendChild( theFrm );
	}

	// Start session
	this.initSession( id, host );
}

NAWebCollab.prototype.startNewSession = function()
{
	// Stop polling session - if needed
	this.stopSessionPolling();

	// Do not delete here since the delete process
	// may not happen until after the cookie is re-set
	// and that causes other problems. Within this feature
	// a cookie set to "null" is considered deleted
	SetCookie( "WCS", "null" );
	
	// Initialize / Re-initialize the param map
	this.m_theParams = this.m_theParams = new Object();
	
	// Remove old reference to NAServerComm - if one exists
	this.m_theServer = null;

	// Initialize session with server
	this.initSession();
}

/**
 * Initiate web collaboration session
 *
 * @param id	Web Collaboration session id
 */
NAWebCollab.prototype.initSession = function( id, host )
{
	// Verify that the cookie sync page will not execute even if it's
	// called from an external source
	
	if( g_currentURL.indexOf( g_cookieSyncPage ) >= 0 )
		return;

	// Disallow redundant calls
	if( this.m_theServer != null )
	{ 
		CheckWCResponse();
		if(id != null && id != 'undefined' && parent == self)
		{
			this.propagateDeltaCall(window.top, "g_theWCObj.initSession('" + id + "', '" + host + "');" );
		}
		return;
	}
	this.debugLogWrite("executing NAWebCollab.initsession");

	this.setFrameIndex();
	this.m_theServer = new NAServerComm();
	this.m_theServer.setListener( this );
	if( id == null )
	{
		CheckWCResponse();
		var wcsinfo = ParseWCS( GetCookie( "WCS" ) );
		this.m_theSessId = wcsinfo.id;
		if( this.m_theSessId == null )
		{
			// C R E A T I N G   N E W   S E S S I O N
			// ---------------------------------------
			// Do not initialize input values because it will cause
			// a bulk publish when the session becomes active
			// /////////////////////////////////////////////////////////
			if(this.m_theServer)
				this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=init", RandomNum() );
			return;
		}

		// If the cookie contains host info - set it here
		if( wcsinfo.host != null )
		{
			this.m_theHost = wcsinfo.host;
		}
		
		// Propagate this call
		this.makeMethodCall("g_theWCObj.initSession();");
	}
	else
	{
		// Set session id from parameter
		var bSet = false;
		if(parent == self && this.m_theSessId == null)
			bSet = true;
		this.m_theSessId = id;

		// Reset session host
		if( host != null )
		{
			this.m_theHost = host;
		}
		if(bSet)
		{
			this.propagateMethodCall( window.top, "g_theWCObj.initSession('" + id + "', '" + host + "');" );
		}	
	}

	// J O I N I N G   A N   E X I S T I N G   S E S S I O N
	// -----------------------------------------------------
	// Skip the initialization process and simple join and activate session
	// /////////////////////////////////////////////////////////////////////
	
	// Recording the existing input values disables the initial
	// bulk publish when the session becomes active
	this.initInputs();

	// Send session activation request
	//this.activateSession( true );

	// Start polling server for updates
	this.startSession();
	
}

/**
 * Initiate the process of polling input values and publishing changes
 *
 */
NAWebCollab.prototype.startSessionPolling = function()
{
	// Publish cookies to server
	if( this.m_sesActive == true )
		this.publishCookies();

	// Start polling
	//if( document.getElementsByTagName("FRAMESET").length > 0 ) return;
	this.stopSessionPolling();
	this.resetIntervalTimeout();
	this.m_theInterval = window.setInterval( "g_theWCObj.pollSession();", 1000 );
	this.debugLogWrite("Session started : " + this.m_theSessId);

	// Disable context menu (security fix)
	//document.body.oncontextmenu = function(){return false;}
}

/**
 * Shutdown the process of polling input values and publishing changes
 *
 */
NAWebCollab.prototype.stopSessionPolling = function()
{
	if( this.m_theInterval != g_invalidHandle )
	{
		window.clearInterval( this.m_theInterval );
		this.m_theInterval = g_invalidHandle;
		return true;
	}
	return false;
}

/**
 * Initiate the process of polling input values and publishing changes
 *
  */
NAWebCollab.prototype.startSession = function()
{
	// Check session id property
	if( this.m_theSessId == null )
	{
		alert( "ERROR: no session found" );
		return;
	}

	// Re-write post forms on the page to point to the proxy
	//this.rewritePOSTs( this.m_theSessId );

	// Create pointer
	this.m_thePtr 					= document.createElement( "DIV" );
	this.m_thePtr.id 				= "WC_PTR";
	this.m_thePtr.innerHTML 		= "<img src='" + this.m_theHost + "/NetAgent/webcollab/images/arrow_right_red.png'/>";
	this.m_thePtr.style.position 	= "absolute";
	this.m_thePtr.style.visibility	= "hidden";
	this.m_thePtr.style.top 		= "0px";
	this.m_thePtr.style.left 		= "0px";
	document.body.appendChild( this.m_thePtr );

	// Request settings from server
	this.requestSettings();
}

/**
 * Iterates all frames recursively and execute function call
 *
 * @param frame		Frame to start recursing
 * @param func		Function to execute
 */
NAWebCollab.prototype.propagateMethodCall = function( frame, func )
{
	for( var i = 0; i < frame.frames.length; i++ )
	{
		var oFrame = frame.frames[i];
		try
		{
			if(typeof(oFrame.g_theWCObj) != 'undefined')
				eval("oFrame." + func);
		}
		catch(e)
		{
			this.debugLogWrite("Exception caught in propagateMethodCall : " + e.message);
		}
		if( oFrame.frames.length > 0 )
		{
			this.propagateMethodCall( oFrame, func );
		}
	}
}

NAWebCollab.prototype.propagateDeltaCall = function( frame, func )
{
	for( var i = 0; i < frame.frames.length; i++ )
	{
		var oFrame = frame.frames[i];
		try
		{
			var temp = null;
			if(typeof(oFrame.g_theWCObj) != 'undefined')
			{
				eval("temp = oFrame.g_theWCObj.m_theServer");
				if(temp == null)
					eval("oFrame." + func);
			}
		}
		catch(e)
		{
			this.debugLogWrite("Exception caught in propagateDeltaCall : " + e.message);
		}
		if( oFrame.frames.length > 0 )
		{
			this.propagateDeltaCall( oFrame, func );
		}
	}
}

/**
 * Execute function call to all child frames, if they exist
 *
 * @param func		Function to execute
 */
NAWebCollab.prototype.makeMethodCall = function( func )
{
	// To stop runaway function calls we only allow this propagation
	// if we are starting from the root frame. The only case where
	// this is not sufficiant is "initSession" which is handled in
	// a special way.
	if( parent == self )
	{
		this.propagateMethodCall( window.top, func );
	}
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	D O C U M E N T   A L T E R I N G   M E T H O D S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Document altering routine used to rewrite form posts to target
 * the web collaboration proxy server instead of the normal host
 */

NAWebCollab.prototype.rewritePOSTs = function()
{
	// Rewrite all form actions
	var oForms = document.getElementsByTagName("FORM");
	for( var i = 0; i < oForms.length; i++ )
	{
		var oForm = oForms[i];
		if( oForm.attributes["method"].value.toUpperCase() == "POST" )
		{
			// NOTE: We need this because "oForm.action" will return an object if there
			//    is a child node named "action"
			var sAction = XML_GetNodeAttribute(oForm,"action");
			if( sAction.indexOf("wcisapi.dll") < 0 )
			{
				// Rewrite action to be absolute
				var fullAction = MakeLinkAbsolute(sAction);

				// Record change for undo later
				this.m_events.recordEvent("form_proxy_rewrite", {index:i,action:fullAction} );

				// Make change to point to proxy
				XML_SetNodeAttribute( oForm, "action", this.m_theHost + g_wcs_path + "?cmd=www&ses=" + this.m_theSessId + "&frm=" + this.m_frameIdx + "&url=" + encodeURI(fullAction) );
			}
		}
	}
}

NAWebCollab.prototype.rewriteAnchors = function()
{
	// Rewrite all anchors
	var oAnchors = document.getElementsByTagName("A");
	for( var i = 0; i < oAnchors.length; i++ )
	{
		var oAnchor = oAnchors[i];
		var sHref = oAnchor.href;
		
		// Don't rewrite JavaScript code
		if( sHref.toLowerCase().indexOf("javascript:") == 0 ) continue;

		if( sHref.indexOf("wcisapi.dll") < 0 )
		{
			// Record change for undo later
			this.m_events.recordEvent("anchor_proxy_rewrite", {index:i,href:sHref} );

			// Rewrite anchor to be absolute
			var fullHref = MakeLinkAbsolute(sHref);

			// Make change to point to proxy
			oAnchor.href = this.m_theHost + g_wcs_path + "?cmd=www&ses=" + this.m_theSessId + "&frm=" + this.m_frameIdx + "&url=" + escape(fullHref);
		}
	}
}

NAWebCollab.prototype.undoForms = function(evt)
{
	// Rewrite all form actions
	var oForms = document.getElementsByTagName("FORM");
	for( var i = 0; i < oForms.length; i++ )
	{
		var oForm = oForms[evt.index];
		XML_SetNodeAttribute( oForm, "action", evt.action );
	}
}

NAWebCollab.prototype.undoAnchors = function(evt)
{
	// Rewrite all anchors
	var oAnchors = document.getElementsByTagName("A");
	for( var i = 0; i < oAnchors.length; i++ )
	{
		var oAnchor = oAnchors[evt.index];
		XML_SetNodeAttribute( oAnchor, "href", evt.href );
	}
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	F O R M   I N P U T   M E T H O D S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/*
shared input types
------------------
checkbox
file
hidden
password
radio
text

*/

NAWebCollab.prototype.getInputIndex = function( obj )
{
	var sName = XML_GetNodeAttribute(obj,"name");
	if( sName.length > 0 )
	{
		var elems = document.getElementsByName(sName);
		for( var i = 0; i < elems.length; i++ )
			if( obj === elems[i] ) return i;
	}
	return -1
}

/**
 * Iterates all input elements on the page and records the initial values
 */
NAWebCollab.prototype.initInputs = function()
{
	for(var x = 0; x < this.m_UITags.length; x++)
	{
		var inputElems = document.getElementsByTagName( this.m_UITags[x] );
		for( var i = 0; i < inputElems.length; i++ )
		{
			var inputElem = inputElems[i];
			
			// Get input element index based on name
			var inputIdx = this.getInputIndex(inputElem);
			if( inputIdx < 0 ) continue;
			
			// Determine input parameter hash
			var sParamHash = inputElem.name + "~" + inputIdx;

			switch( this.m_UITags[x] )
			{
			case "INPUT":
				if(	inputElem.type == "text" ||
					inputElem.type == "hidden" ||
					inputElem.type == "password" ||
					inputElem.type == "file" )
				{
					this.m_theParams[sParamHash] = escape(inputElem.value);
				}
				else if( inputElem.type == "checkbox" )
				{
					this.m_theParams[sParamHash] = inputElem.checked;
				}
				else if( inputElem.type == "radio" && inputElem.checked == true )
				{
					if(inputElem.id != null && inputElem.id != 'undefined' && inputElem.id != "")
						this.m_theParams[inputElem.name] = inputElem.value + "$$$;$$$" + inputElem.id;
					else
						this.m_theParams[inputElem.name] = inputElem.value;
				}
				break;
			case "SELECT":
				if(inputElem.multiple)
				{
					var temptext = "";
					for(var i=0;i<inputElem.options.length;i++)
					{
						if(inputElem.options[i].selected)
						{
							temptext = temptext + i + ",";
						}	
					}
					var len = temptext.length-1;
					temptext = temptext.substr(0,len);
					this.m_theParams[sParamHash] = escape(temptext);
				}
				else
				{
					var temptext = "";
					temptext = inputElem.selectedIndex;
					this.m_theParams[sParamHash] = escape(temptext);
				}
				break;	
			default:
				this.m_theParams[sParamHash] = escape(inputElem.value);
				break;
			}
		}
	}
}

/**
 * Iterates all input elements on the page and publishes any values which have
 * changes since the last publication.
 */
NAWebCollab.prototype.publishInputs = function()
{
	// Check for globally blocked parameters
	if( this.m_paramStatus["*"] != null &&
		this.m_paramStatus["*"] == PRIVATE && this.m_clientType != CUSTOMER)
			return;
					
	var paramArray = new Array();
	var bChanges = false;
	for(var x = 0; x < this.m_UITags.length; x++)
	{
		var inputElems = document.getElementsByTagName( this.m_UITags[x] );
		for( var i = 0; i < inputElems.length; i++ )
		{
			// Get input element
			var inputElem = inputElems[i];

			// Get input element index based on name
			var inputIdx = this.getInputIndex(inputElem);
			if( inputIdx < 0 ) continue;
			
			// Determine input parameter hash
			var sParamHash = inputElem.name + "~" + inputIdx;

			// Check for exclusions
			if( inputElem.name.length == 0 ) continue;
			if( inputElem.name.length == "__VIEWSTATE" ) continue;		// This input is way too big

			var isBlocked = false;
			if(this.m_paramStatus["*"] != null && this.m_paramStatus["*"] == PRIVATE)
				isBlocked = true;
			
			
			// Check for specified blocked parameter
			if( this.m_paramStatus[inputElem.name] != null &&
				this.m_paramStatus[inputElem.name] == PRIVATE && this.m_clientType != 0)
					continue;
			
			if( this.m_paramStatus[inputElem.name] != null &&
				this.m_paramStatus[inputElem.name] == PRIVATE && this.m_clientType == 0)
					isBlocked = true;	
					
			// Check for changes and publish deltas
			switch( this.m_UITags[x] )
			{
			case "INPUT":
				var paramType = inputElem.type.toLowerCase();
				if(	paramType == "text" ||
					paramType == "hidden" ||
					paramType == "password" ||
					paramType == "file" )
				{
					if( this.m_theParams[sParamHash] == null ||
						unescape(this.m_theParams[sParamHash]) != inputElem.value )
					{
						if(isBlocked && paramType == "text")
						{
							var temp1 = "$$blocked$$";
							for(var t1=0; t1<inputElem.value.length; t1++)
								temp1 = temp1 + "*";
							paramArray.push( "<param type='" + paramType + "' name='" + inputElem.name + "' index='" + inputIdx + "'>" + escape(temp1) + "</param>" );
						}
						else
							paramArray.push( "<param type='" + paramType + "' name='" + inputElem.name + "' index='" + inputIdx + "'>" + escape(inputElem.value) + "</param>" );
						this.m_theParams[sParamHash] = escape(inputElem.value);
						bChanges = true;
					}
				}
				else if( paramType == "checkbox" )
				{
					if( this.m_theParams[sParamHash] == null ||
						this.m_theParams[sParamHash] != inputElem.checked )
					{
						if(!isBlocked)
						{
							paramArray.push( "<param type='" + paramType + "' name='" + inputElem.name + "' index='" + inputIdx + "'>" + inputElem.checked + "</param>" );
							bChanges = true;
						}
						this.m_theParams[sParamHash] = inputElem.checked;
					}
				}
				else if( paramType == "radio" && inputElem.checked == true )
				{
					var tempVal;
					if( this.m_theParams[inputElem.name] != null)
					{
						var iDelim = this.m_theParams[inputElem.name].indexOf( "$$$;$$$" );
						tempVal = "";
						if( iDelim >= 0 )
						{
							tempVal = this.m_theParams[inputElem.name].substr( 0, iDelim );
						}
						else
							tempVal = this.m_theParams[inputElem.name];
					}
					if( this.m_theParams[inputElem.name] == null || tempVal != inputElem.value )
					{
						if(inputElem.id != null && inputElem.id != 'undefined' && inputElem.id != "")
						{
							if(!isBlocked)
							{
								paramArray.push( "<param type='" + paramType + "' name='" + inputElem.name + "' index='0'>" + inputElem.value + "$$$;$$$" + inputElem.id + "</param>" );
								bChanges = true;
							}
							this.m_theParams[inputElem.name] = inputElem.value + "$$$;$$$" + inputElem.id;
						}
						else
						{
							if(!isBlocked)
							{
								paramArray.push( "<param type='" + paramType + "' name='" + inputElem.name + "' index='0'>" + inputElem.value + "</param>" );
								bChanges = true;
							}
							this.m_theParams[inputElem.name] = inputElem.value;
						}
					}
				}
				break;
			case "SELECT":	
				var temptext = "";
				var sParamTyp = this.m_UITags[x].toLowerCase();
				if(inputElem.multiple)
				{
					var tempText = "";
					for(var ii=0;ii<inputElem.options.length;ii++)
					{
						if(inputElem.options[ii].selected)
						{
							temptext = temptext + ii + ",";
						}	
					}
					var len = 0;
					if(temptext.length > 0)
					{
						len = temptext.length-1;
						temptext = temptext.substr(0,len);
					}
				}
				else
				{
					temptext = inputElem.selectedIndex;
				}
				if( this.m_theParams[sParamHash] == null ||
					unescape(this.m_theParams[sParamHash]) != temptext )
				{
					paramArray.push( "<param type='" + sParamTyp + "' name='" + inputElem.name + "' index='" + inputIdx + "'>" + escape(temptext) + "</param>" );
					this.m_theParams[sParamHash] = escape(temptext);
					bChanges = true;
				}
				break;
			default:
				var sParamType = this.m_UITags[x].toLowerCase();
				var strVal = escape((navigator.userAgent.toLowerCase().indexOf("safari")>-1 || navigator.userAgent.toLowerCase().indexOf("firefox")>-1)?inputElem.value.replace(/\x0A/ig, String.fromCharCode(13) + String.fromCharCode(10)):inputElem.value);
				if( this.m_theParams[sParamHash] == null ||
					this.m_theParams[sParamHash] != strVal)
				{
					if(isBlocked)
					{
						var temp3 = (navigator.userAgent.toLowerCase().indexOf("safari")>-1 || navigator.userAgent.toLowerCase().indexOf("firefox")>-1)?inputElem.value.replace(/\x0A/ig, String.fromCharCode(13) + String.fromCharCode(10)):inputElem.value;
						var temp2 = "";
						for(var t2=0; t2<temp3.length; t2++)
						{
							if(temp3.charAt(t2) == String.fromCharCode(13) || temp3.charAt(t2) == String.fromCharCode(10))
								temp2 = temp2 + temp3.charAt(t2);
							else
								temp2 = temp2 + "*";
						}
						temp2 = "$$blocked$$" + temp2;
						paramArray.push( "<param type='" + paramType + "' name='" + inputElem.name + "' index='" + inputIdx + "'>" + escape(temp2) + "</param>" );
					}
					else
						paramArray.push( "<param type='" + sParamType + "' name='" + inputElem.name + "' index='" + inputIdx + "'>" + strVal + "</param>" );
					this.m_theParams[sParamHash] = strVal;
					bChanges = true;
				}
				break;
			}
		}
	}

	if( bChanges == true )
	{
		var sendBuffer = "";
		while( paramArray.length > 0 )
		{
			var paramXML = paramArray.shift();
			if( paramXML.length <= g_bytesLimit )		// Ignore single input parameter which are over the size limit
			{
				if( (sendBuffer.length + paramXML.length) > g_bytesLimit )
				{
					this.publishParameters(sendBuffer);
					sendBuffer = paramXML;
				}
				else
				{
					sendBuffer += paramXML;
				}
			}
			else
			{
				this.debugLogWrite("Input parameter exceeding size limit of " + g_bytesLimit );
			}
		}
		this.publishParameters(sendBuffer);
	}
}

/**
 * Iterates all input elements from query response and update any values which have
 * changes since the last query.
 */
NAWebCollab.prototype.updateInputs = function( xml_doc )
{
	// Iterate parameters and update the values
	var params = xml_doc.getElementsByTagName("param");
	for( var i = 0; i < params.length; i++ )
	{
		var param = params[i];
		var param_name = XML_GetNodeAttribute(param,"name");
		var param_index = XML_GetNodeAttribute(param,"index");
		
		// Determine input parameter hash
		var sParamHash = param_name + "~" + param_index;
		
		var bBlocked = false;
		
		// Check for blocked parameter
		if( this.m_paramStatus[param_name] != null &&
			this.m_paramStatus[param_name] == PRIVATE && this.m_clientType == CUSTOMER)
				continue;
		if( this.m_paramStatus["*"] != null &&
			this.m_paramStatus["*"] == PRIVATE && this.m_clientType == CUSTOMER)
				continue;
		if((this.m_paramStatus["*"] != null && this.m_paramStatus["*"] == PRIVATE) || (this.m_paramStatus[param_name] != null && this.m_paramStatus[param_name] == PRIVATE)) 
			bBlocked = true;
		var param_type = XML_GetNodeAttribute(param,"type");
		switch( param_type )
		{
		case "radio":
			var inputElems = document.getElementsByName(param_name);
			var tempData = XML_GetNodeText(param);
			var tempVal;
			var iDelim = tempData.indexOf( "$$$;$$$" );
			var selectId = "";
			if( iDelim >= 0 )
			{
				tempVal = tempData.substr( 0, iDelim );
				selectId = tempData.substr( iDelim + 7 );
			}
			else
				tempVal = tempData;
			if(selectId.length > 0)
			{
				if(document.getElementById(selectId) != null && document.getElementById(selectId).checked != null)
				{
					if(this.m_theParams[document.getElementById(selectId).name] == null || this.m_theParams[document.getElementById(selectId).name] != XML_GetNodeText(param))
					{
						this.m_theParams[document.getElementById(selectId).name] = XML_GetNodeText(param);
						document.getElementById(selectId).checked = true;
					}
				}
			}
			else
			{
				for( var ii = 0; ii < inputElems.length; ii++ )
				{
					var inputElem = inputElems[ii];
					if( inputElem != null && inputElem.checked != null && inputElem.value == XML_GetNodeText(param) )
					{
						if( this.m_theParams[inputElem.name] == null || this.m_theParams[inputElem.name] != XML_GetNodeText(param) )
						{
							this.m_theParams[inputElem.name] = XML_GetNodeText(param);
							inputElem.checked = true;
						}
					}
				}
			}
			break;
		case "checkbox":
			var inputElem = document.getElementsByName(param_name)[param_index];
			if( inputElem != null )
			{
				var bVal;
				if( XML_GetNodeText(param) == "true" ) bVal = true;
				else bVal = false;
				if( this.m_theParams[sParamHash] == null || this.m_theParams[sParamHash] !=  bVal )
				{
					this.m_theParams[sParamHash] =  bVal;
					inputElem.checked =  bVal;
				}
			}
			break;
		case "select":
			var inputElem = document.getElementsByName(param_name)[param_index];
			if( inputElem != null )
			{ 
				var textVal = unescape( XML_GetNodeText(param) );
				var splitArr;
				if(inputElem.multiple)
				{
					if(textVal.length > 0)
						splitArr = textVal.split(",");
					if( this.m_theParams[sParamHash] == null || unescape(this.m_theParams[sParamHash]) != textVal )
					{
						this.m_theParams[sParamHash] = escape(textVal);
						inputElem.selectedIndex = -1;
						if(splitArr)
						{
							for(var n=0;n<splitArr.length;n++)
							{
								inputElem.options[splitArr[n]].selected = true;
								continue;
							}
						}
					}
				}
				else
				{	
					if( this.m_theParams[sParamHash] == null || unescape(this.m_theParams[sParamHash]) != textVal )
					{ 
						this.m_theParams[sParamHash] = escape(textVal);
						inputElem.options[textVal].selected = true;
					}
				}
				
			}
			break;
		default:
			var inputElem = document.getElementsByName(param_name)[param_index];
			if( inputElem != null )
			{ 
				var textVal = unescape( XML_GetNodeText(param) );
				var splitArr;
				if(bBlocked)
				{
					var iDelim1 = textVal.indexOf( "$$blocked$$" );
					var tempVal1 = "";
					if( iDelim1 == 0 )
					{
						tempVal1 = textVal.substr(11);
					}
					else
						tempVal1 = textVal;
					textVal = tempVal1;
				}
				if(this.m_theParams[sParamHash] == null || unescape(this.m_theParams[sParamHash]) != textVal)
				{
					this.m_theParams[sParamHash] = escape(textVal);
					inputElem.value = textVal;
				}
			}
			break;
		}
	}
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	C O O K I E   M E T H O D S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Iterates all cookies and publishes all cookie values.
 */
NAWebCollab.prototype.publishCookies = function()
{
	//if( this.m_clientType != CUSTOMER ) return;
	
	//var bChanges = false;
	var postData = "<cookies>";

	var sTmp = document.location.href.toLowerCase();
	//if( sTmp.indexOf( "wcisapi.dll" ) < 0 )	// Don't publish cookies from proxy page
	{			
		// Cookies are separated by semicolons
		var aCookie = document.cookie.split( "; " );
		for( var i = 0; i < aCookie.length; i++ )
		{
			// A name/value pair (a crumb) is separated by an equal sign
			var crumbName, crumbValue;
			var iDelim = aCookie[i].indexOf( "=" );
			if( iDelim >= 0 )
			{
				crumbName = aCookie[i].substr( 0, iDelim );
				crumbValue = aCookie[i].substr( iDelim + 1 );
				if( crumbName.toUpperCase() == "WCS" ) continue;
				postData += "<cookie name='" + crumbName + "'>" + escape(crumbValue) + "</cookie>";
				//this.debugLogWrite("export cookie {" + crumbName + "==>" + decodeURI(crumbValue) + "}");
			}
		}
	}
	postData += "</cookies>";

	// Send cookies to server
	if(this.m_theServer)
		this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=cookies&ses=" + this.m_theSessId, RandomNum(), postData );
}

/**
 * Iterates all cookies and deletes them.
 */
NAWebCollab.prototype.deleteCookies = function()
{
	deleteAllCookies();
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	P O I N T E R   M E T H O D S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Enter/Leave pointer mode
 */
NAWebCollab.prototype.enablePointerMode = function( enable )
{
	if( enable == true )
	{
		//this.m_uiMode = POINTER;
		this.startPointerMode();
	}
	else
	{
		//this.m_uiMode = NORMAL;
		if(this.m_theSessId)
			this.stopPointerMode();
	}
	if(enable)
		this.makeMethodCall("g_theWCObj.enablePointerMode(true);");
	else
		this.makeMethodCall("g_theWCObj.enablePointerMode(false);");
}

/**
 * Publish pointer position
 *
 * @param name	Name of element to recieve pointer
 */
NAWebCollab.prototype.sendPointer = function( name )
{
	var sessId = this.m_theSessId;
	if( sessId == null )
	{
		alert( "ERROR: no session found" );
		return;
	}
	
	if( this.m_theServer != null )
	{
		this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=ptr&ses=" + sessId + "&frm=" + this.m_frameIdx + "&in=" + name, RandomNum() );
	}
}

/**
 * Publish pointer position
 *
 * @param name	Name of element to recieve pointer
 */
NAWebCollab.prototype.handleMouseOver = function()
{
	if( this.m_selectedObj == null )
	{
		// Set selected object
		this.m_selectedObj = event.srcElement;
		// Record currently selected objects styles
		this.m_lastStyle_BACKGROUNDCOLOR	= event.srcElement.style.backgroundColor;
		this.m_lastStyle_CURSOR 			= event.srcElement.style.cursor;
		this.m_lastStyle_BORDERWIDTH 		= event.srcElement.style.borderWidth;
		this.m_lastStyle_BORDERCOLOR 		= event.srcElement.style.borderColor;
	
		// Mark as selected
		event.srcElement.style.backgroundColor	= g_theWCObj.m_hltColor;
		event.srcElement.style.cursor 			= "pointer";
		event.srcElement.style.borderWidth 		= "2px";
		event.srcElement.style.borderColor 		= g_theWCObj.m_hltColor;
	}
}

NAWebCollab.prototype.handleMouseOut = function()
{
	if( this.m_selectedObj != null )
	{
		// Reset previously selected object styles
		this.m_selectedObj.style.backgroundColor	= this.m_lastStyle_BACKGROUNDCOLOR;
		this.m_selectedObj.style.cursor 			= this.m_lastStyle_CURSOR;
		this.m_selectedObj.style.borderWidth 		= this.m_lastStyle_BORDERWIDTH;
		this.m_selectedObj.style.borderColor 		= this.m_lastStyle_BORDERCOLOR;

		// Reset selected object to null
		this.m_selectedObj = null;
	}
}

NAWebCollab.prototype.handleClick = function()
{
	g_theWCObj.sendPointer( this.m_selectedObj.name );
	//return false;
}

NAWebCollab.prototype.startPointerMode = function()
{
	for(var x = 0; x < this.m_UITags.length; x++)
	{
		var inputElems = document.getElementsByTagName( this.m_UITags[x] );
		for( var i = 0; i < inputElems.length; i++ )
		{
			var inputElem = inputElems[i];
			if(inputElem.type != "button" && inputElem.type != "submit" && inputElem.type != "reset")
			{
				inputElem.onclick = this.handleClick;
				inputElem.onmouseover = this.handleMouseOver;
				inputElem.onmouseout = this.handleMouseOut;
				inputElem.readOnly = true;
			}
		}
	}
}

NAWebCollab.prototype.stopPointerMode = function()
{
	g_theWCObj.sendPointer( "" );
	for(var x = 0; x < this.m_UITags.length; x++)
	{
		var inputElems = document.getElementsByTagName( this.m_UITags[x] );
		for( var i = 0; i < inputElems.length; i++ )
		{
			var inputElem = inputElems[i];
			if(inputElem.type != "button" && inputElem.type != "submit" && inputElem.type != "reset")
			{
				inputElem.onclick = null;
				inputElem.onmouseover = null;
				inputElem.onmouseout = null;
				inputElem.readOnly = false;
			}
		}
	}
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	H I G H L I G H T I N G   M E T H O D S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

NAWebCollab.prototype.publishHightlighting = function()
{
	var sessId = this.m_theSessId;
	if( sessId == null )
	{
		alert( "ERROR: no session found" );
		return;
	}
	
	if( this.m_theServer != null )
	{
		var selectionRange = this.getSelectionRange();
		if(this.m_theServer)
			this.m_theServer.sendRequest( this.m_theHost + g_wcs_path + "?cmd=hlt&ses=" + sessId + "&frm=" + this.m_frameIdx + "&start=" + selectionRange.start + "&end=" + selectionRange.end, RandomNum() );
	}
	
	this.makeMethodCall("g_theWCObj.publishHightlighting();");
}

NAWebCollab.prototype.getSelectionRange = function()
{
	try
	{
		if( document.selection )
		{
			var sRange, sStoredRange;
			var selStart = -1, selEnd;
			var range = document.selection.createRange();
			var stored_range = range.duplicate();
			//stored_range.moveToElementText( document.body );
			//stored_range.setEndPoint( 'EndToEnd', range );
			do
			{
				//selStart++;
				//stored_range.collapse();
				//stored_range.moveToElementText( document.body );
				//stored_range.setEndPoint( 'StartToStart', range );
				stored_range.moveToElementText( document.body );
				stored_range.setEndPoint( 'EndToEnd', range );
				stored_range.moveStart( "character", ++selStart );
				//stored_range.setEndPoint( 'EndToEnd', range );
			}
			while( stored_range.htmlText.length > range.htmlText.length );
			//while( stored_range.isEqual(range) == false );
			selEnd = selStart + range.text.length;
			this.highlightSelection( range );
			SetGlobalCursor("auto");
			return{ start:selStart, end:selEnd };
		}
	}
	catch(e)
	{
		SetGlobalCursor("auto");
	}
}

NAWebCollab.prototype.createSelection = function( selstart, selend )
{
	if( document.body && document.body.createTextRange )	// IE
	{
		var oRange = document.body.createTextRange();
		oRange.collapse();
		oRange.moveStart( "character", selstart );
		oRange.moveEnd( "character", selend-selstart );
		oRange.select();
		this.highlightSelection( oRange );
	}
	else													// Firefox
	{
		oSelection = window.getSelection();
		if( oSelection.rangeCount > 0 ) oSelection.removeAllRanges();
		oRange = document.createRange();
		oRange.setStart( document.body, selstart );
		oRange.setEnd( document.body, selend );
		oSelection.addRange( oRange );
	}
}
						
NAWebCollab.prototype.highlightSelection = function( range )
{
	this.removeAllHighlighting();
	if( document.body && document.body.createTextRange )	// IE
	{
		range.pasteHTML("<SPAN ID='highlightmarker' STYLE='background:" + this.m_hltColor + ";border-width:2px;border-color:silver;border-style:solid;'>" + range.htmlText + "</SPAN>");
	}
	else													// Firefox
	{
	}
}

NAWebCollab.prototype.removeAllHighlighting = function()
{
	var i, hltr = document.getElementById("highlightmarker");
	if( hltr != null )
	{
		hltr.style.background = "";
		hltr.style.borderWidth = "0px";
		hltr.style.borderColor = "";
		hltr.style.borderStyle = "none";
		hltr.id = '';
	}
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	D E B U G   L O G   M E T H O D S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

NAWebCollab.prototype.debugLogWrite = function( msg )
{
	this.m_dbgLog.push( msg );
}

NAWebCollab.prototype.debugLogDisplay = function()
{
	var theDebugDisp = document.getElementById( "WC_DEBUG" );
	if( theDebugDisp == null )
	{
		var screenwidth = getClientWidth();
		var screenHeight = getClientHeight();
		var winWidth = 460;
		var winHeight = 400;

		// Create display area
		theDebugDisp 						= document.createElement( "SPAN" );
		theDebugDisp.id 					= "WC_DEBUG";
		theDebugDisp.style.position 		= "absolute";
		theDebugDisp.style.visibility		= "visible";
		theDebugDisp.style.top 				= ((screenHeight - winHeight) / 2) + "px";
		theDebugDisp.style.left 			= ((screenwidth - winWidth) / 2) + "px";
		theDebugDisp.style.width			= winWidth + "px";
		theDebugDisp.style.height			= winHeight + "px";
		theDebugDisp.style.backgroundColor 	= "yellow";
		theDebugDisp.style.color 			= "navy";
		theDebugDisp.style.overflow			= "scroll";
		theDebugDisp.style.border 			= "1px solid navy";
		theDebugDisp.style.font 			= "8pt verdana";
		document.body.appendChild( theDebugDisp );
		theDebugDisp.innerHTML += "<strong>Last Response:</strong><xmp>" + this.m_dbgLastResponse + "</xmp>";
		theDebugDisp.innerHTML += "<strong>User Type:</strong> ";
		if( this.m_clientType == CUSTOMER ) theDebugDisp.innerHTML += "CUSTOMER";
		else if( this.m_clientType == AGENT ) theDebugDisp.innerHTML += "AGENT";
		else theDebugDisp.innerHTML += "UNKNOWN";
		
		// Write out all cookies ///////////////////////
		theDebugDisp.innerHTML += "<xmp>ALL CURRENT COOKIES..</xmp>";
		var aCookie = document.cookie.split( "; " );
		for( var i = 0; i < aCookie.length; i++ )
		{
			//theDebugDisp.innerHTML += "<xmp>" + unescape(aCookie[i]) + "</xmp>";
			theDebugDisp.innerHTML += "<xmp>" + aCookie[i] + "</xmp>";
		}
		theDebugDisp.innerHTML += "<xmp>END OF COOKIES</xmp>";
		// /////////////////////////////////////////////
		
		theDebugDisp.innerHTML += "<br><hr><br><strong>Logs:</strong>";
		for(var x = 0; x < this.m_dbgLog.length; x++)
			theDebugDisp.innerHTML += "<xmp>" + this.m_dbgLog[x] + "</xmp>";
	}
}

NAWebCollab.prototype.debugLogRemove = function()
{
	var theDebugDisp = document.getElementById( "WC_DEBUG" );
	if( theDebugDisp != null )
	{
		document.body.removeChild( theDebugDisp );
	}
}

NAWebCollab.prototype.writeCookiesToDebugLog = function()
{
	this.debugLogWrite("ALL CURRENT COOKIES..");

	// Cookies are separated by semicolons
	var aCookie = document.cookie.split( "; " );
	for( var i = 0; i < aCookie.length; i++ )
	{
		//this.debugLogWrite(unescape(aCookie[i]));
		this.debugLogWrite(aCookie[i]);
	}
	
	this.debugLogWrite("END OF COOKIES");
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	P O R T A L   M E T H O D S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Launch portal login page with the appropriate parameters
 *
 * @param id		Web Collaboration session id
 * @param questid	Questionaire id
 * @param portalid	Portal id
 */
NAWebCollab.prototype.launchPortalLogin = function( id, url)
{
	portalLink = "";
	if(id == null)
		portalLink = url + "&nareferer=" + escape(document.location.href) + "&wcs=" + escape("@" + this.m_theHost);
	else
		portalLink = url + "&nareferer=" + escape(document.location.href) + "&wcs=" + escape(id + "@" + this.m_theHost);
	try
	{
	if(TALCOB)
			TALCOB.document.location.href = portalLink;
	}
	catch(e)
	{
		return;
	}
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	M A I N   W E B   C O L L A B O R A T I O N   O B J E C T
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

var g_theWCObj = new NAWebCollab();

//document.body.onresize = function ()
function resizeWindow()
{
	if(g_theWCObj.m_thePtr.style.visibility != "hidden")
	{
		if(g_theWCObj.m_theFocusName != null || g_theWCObj.m_theFocusName != 'undefined' || g_theWCObj.m_theFocusName != "")
		{
			var vins1 = document.getElementsByName(g_theWCObj.m_theFocusName);
			if( vins1 != null && vins1.length > 0 )
			{
				var vin1 = vins1[0];
				vin1.scrollIntoView( false );
				g_theWCObj.m_thePtr.style.visibility = "visible";
				g_theWCObj.m_thePtr.style.left = g_theWCObj.posLeft(vin1) - 50;
				g_theWCObj.m_thePtr.style.top = g_theWCObj.posTop(vin1) - 10;
			}
		}
	}
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	E V E N T   H A N D L E R S
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

/**
 * Use the onload event to determine if a web collaboration session is already in progress
 */
function restartWC()
{
	g_theWCObj.debugLogWrite("CoBrowse attached");

	// Pickup the session through cookie
	wcsinfo = ParseWCS( GetCookie( "WCS" ) );
	if( wcsinfo.id != null )
	{
		// Start monitoring if the session has already been established
		g_theWCObj.initSession( wcsinfo.id, wcsinfo.host );
	}
}

/**
 * Use the onscroll event to determine if an index has been clicked that differs from the current one
 * note: Only changes can be picked up
 */
function scrollWindow()
{
	if( g_currentURL != document.location.href )
	{
		g_currentURL = document.location.href;
		g_theWCObj.pushLocation();
	}
}

function keyPress(e)
{
	var altKey = 0;
	var ctrlKey = 0;
	var keyCode = 0;
	if(window.event)
	{
		altKey = event.altKey;
		ctrlKey = event.ctrlKey;
		keyCode = event.keyCode;
	}
	else
	{
		altKey = e.altKey;
		ctrlKey = e.ctrlKey;
		keyCode = e.which;
	}

	// Disable CTRL-N (security fix)
	//if( ctrlKey == true && keyCode == 78 )
	//	return false;
		
	if( ctrlKey == true && altKey == true && keyCode == 68 )
		g_theWCObj.debugLogDisplay();
	else if( keyCode == 27 )
		g_theWCObj.debugLogRemove();
}

// Attach events to document only if it's not cookiesync
if( g_currentURL.indexOf( g_cookieSyncPage ) < 0 )
{
	// Attach web collab events
	AttachToEvent( window, "load", restartWC );
	AttachToEvent( window, "scroll", scrollWindow );
	AttachToEvent( document, "keydown", keyPress );
	AttachToEvent( document, "onresize", resizeWindow );
}


//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//	E X T E R N A L   A P I
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

document.initSession = function __initSession( id, host )
{
	g_theWCObj.debugLogWrite("executing document.initsession");
	window.setTimeout( "g_theWCObj.initSession( '" + id + "', '" + host + "' );", 10 );
}
document.joinSession = function __joinSession( id, host )
{
	g_theWCObj.debugLogWrite("executing document.joinsession");
	window.setTimeout( "g_theWCObj.joinSession( '" + id + "', '" + host + "' );", 10 );
}
document.enablePointerMode = function __enablePointerMode( enable )
{
	if( enable == true )
		window.setTimeout( "g_theWCObj.enablePointerMode( true );", 10 );
	else
		window.setTimeout( "g_theWCObj.enablePointerMode( false );", 10 );
}
document.publishHightlighting = function __publishHightlighting()
{
	SetGlobalCursor("wait");
	window.setTimeout( "g_theWCObj.publishHightlighting();", 10 );
}
document.activateSession = function __activateSession( active )
{
	if( active == true )
		window.setTimeout( "g_theWCObj.activateSession( true );", 10 );
	else
		window.setTimeout( "g_theWCObj.activateSession( false );", 10 );
}
document.exitSession = function __exitSession()
{
	window.setTimeout( "g_theWCObj.exitSession();", 10 );
}
document.closeSession = function __closeSession()
{
	window.setTimeout( "g_theWCObj.closeSession();", 10 );
}