// Time Script was loaded
var LFStartTime = new Date().getTime();
// helps tell us whats going on in the browser environment.
var browser = new VBrowserDetect();
// this be the main timer
var velaro_lfTimer = false;
// Allow invites to more flag
var vAllowMove = false;

// another browser detection scheme, used by the floating layer
var NS6=false;
var IE4=(document.all);
if (!IE4) {NS6=(document.getElementById);}
var NS4=(document.layers);

// client window sizes
var clientWidth, clientHeight;

// generic object used to hook in to events.
var Obj;

// ensure the timer gets started
var timerStarted = false;
setTimeout( function() { backupCheck(); }, 15000);

// cobrowse variables..
var cobrowseRequestPending=false;
var cobrowseDenied=false;

// array of events that have occurred which need to be sent to server 
var cseCount = 0;
var cse = new Array();
var cseFormCount = 0;
var cseForm = new Array();

// track how long we have been idle on this page
var idleCheck = 0;

// flag telling us the ID of the currently visible invite. -1=proactive request, 0=none
var inviteDisplayed=false;
var currentInvite;

// variables maintaining the state of the current float progress.
var floatX=10;
var floatY=10;
var delayspeed=3;
var lastX=-1;
var lastY=-1;

// constants defining the floatTo and floatFrom integer..
var enumNoFloat = 0;
var enumTopLeft = 1;
var enumTop = 2;
var enumTopRight = 3;
var enumRight = 4;
var enumBottomRight = 5;
var enumBottom = 6;
var enumBottomLeft = 7;
var enumLeft = 8;
var enumUseStartXYPos = 9;
var enumUseEndXYPos = 10;
var enumCenter = 11;

// array of all trigger id's with client side events..
var cseTriggersCount = 0;
var cseTriggers = new Array();
var cseCheckingTrigger=-1;

// array of triggers that actually fired in the most recent
// pass.  this is cleared and repopulated each 5 second interval
// and is used to delete any triggers from teh cseTriggers list
// to ensure we don't try to run any triggers more than once.
var cseTriggersRun = new Array();

// create generic hooks
assignLocalHandlers();  

// primary update image.  
var imagePrimary = document.createElement("IMG");
imagePrimary.name = "lf_img_primary";
imagePrimary.id = "lf_img_primary";
imagePrimary.border = 0;
imagePrimary.setAttribute("alt", "");
imagePrimary.visible = false;
//document.appendChild(imagePrimary);

// single trigger check image.  used and iterated 
// when imagePrimary tells us to.
var imageTrigger = document.createElement("IMG");
imageTrigger.name = "lf_img_trigger";
imageTrigger.id = "lf_img_trigger";
imageTrigger.border = 0;
imageTrigger.setAttribute("alt", "");
imageTrigger.visible=false;
//document.appendChild(imageTrigger);

// a div object must have been placed on the page somewhere
// and it must be called lf_div_invite
var divInvite = findDOMObject("lf_div_invite");
divInvite.name = "lf_div_invite";
divInvite.id = "lf_div_invite";
divInvite.style.display="none";
divInvite.style.position="absolute";
divInvite.style.left="0px";
divInvite.style.top="0px";
divInvite.style.width="0px";
divInvite.style.margin="0px";
divInvite.style.padding="0";
divInvite.style.height="0px";
divInvite.style.zIndex = 99;

// create the hidden iframe that sits within the divInvite
var iframeInvite = findDOMObject("lf_iframe_invite"); 

// don't do anything until the doc is fully loaded..
// then call lfStart();
if (typeof window.addEventListener != 'undefined') {
    if (browser.isSafari) {
        window.addEventListener('load', lfStart(), false);
    }
    else {
        window.addEventListener('load', lfStart, false);
    }
}
else if (typeof document.addEventListener != 'undefined') {
    document.addEventListener('load', lfStart(), false);
}
else if (typeof window.attachEvent != 'undefined') {
    window.attachEvent('onload', lfStart);
}
else {
    if (typeof window.onload == 'function') {
        var existing = onload;
        window.onload = function() {
            existing();
            lfStart();
        };
    }
    else {
        window.onload = lfStart;
    }
}
/*
var loadExistFunc = window.onload;
window.onload = function() {
    if (typeof (loadExistFunc) != "undefined") {
        var functionsValue = new String(loadExistFunc);
        functionsValue = functionsValue.substring(functionsValue.indexOf("{") + 1, functionsValue.length - 2);
        try {
            eval(functionsValue);
        } catch (ex) {
            if (typeof loadExistFunc == 'function')
                loadExistFunc();
        }
    }
    if (!timerStarted) {
        //lfDebug("Onload event triggered");
        // after all that depends on window.onload is called you can call your functions here
        lfStart();
    }
};*/

function backupCheck2() {
    if (!timerStarted) {
        if (typeof (document.readyState) != "undefined") {
            if (document.readyState == "complete") {
                //lfDebug("Onload not working using ReadyState instead");
                lfStart();
                return;
            }
        }
        //lfDebug("ReadyState not complete, restarting");
        setTimeout(function() { backupCheck2(); }, 10);
    }
}
setTimeout(function() { backupCheck2(); }, 10);

// handle Ending Cobrowse
var endCobrowseProcessed = false;

function backupCheck() {
    if (!timerStarted) {
        //lfDebug("Onload event NOT triggered, using Backup");
        lfStart();
    }
}

function lfStart() {
    if (timerStarted)
        return; 
        
    // assign a cookie to keep this visitors sessionid for all time.
    setCookie('velarosession', vSessionid, 365);    
    
    // execute all actions that need to be run immediately.
    executeActions();

    // hook into update check even if there are no client side events
    // because we need to keep the visitor session open on our servers.
    lfStartTimer();
}

function setCookie(c_name, value, expiredays) {
    if (typeof useVelaroCookies != "undefined" && useVelaroCookies) {
        var exdate = new Date();
        exdate.setDate(exdate.getDate() + expiredays);
        document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
    }
}

function lfStartTimer()
{
    timerStarted = true;
    velaro_lfTimer = setTimeout(function() { primaryCheck(); }, updateInterval);
}

function executeActions() {
    //lfDebug("executeActions: Content(" + contents.length + ") Invites(" + invites.length + ") alerts(" + alerts.length + ")");
    // content first...
    var lcv=0;
    while(lcv<contents.length) {
        if (!contents[lcv].clientSideEvents) {
            executeActionContent(contents[lcv]);
        }
        else {
            if (!arrayContains(cseTriggers, contents[lcv].triggerID)) {
                cseTriggers[cseTriggersCount++] = contents[lcv].triggerID;
            }
            lcv++;
        }
    }  
    
    // invites next...
    lcv=0;
    while(lcv<invites.length) {
        if (!invites[lcv].clientSideEvents) {
            executeActionInvite(invites[lcv]);
        }
        else {
            if (!arrayContains(cseTriggers, invites[lcv].triggerID)) {
                cseTriggers[cseTriggersCount++] = invites[lcv].triggerID;
            }
            lcv++;
        }
    }
    
    // alerts next... no such thing as non-clientside alerts
    lcv=0;
    while (lcv < alerts.length) {
        if (!arrayContains(cseTriggers, alerts[lcv].triggerID)) {
            cseTriggers[cseTriggersCount++] = alerts[lcv].triggerID;
        }
        lcv++;
    }
        
    // with the trigger list completely built, sort it.
    cseTriggers = cseTriggers.sort();
}

// refresh the primary image check and see if there are any triggers that could potentially fire as a result.
function primaryCheck() {
  //lfDebug("primaryCheck called after");
  // increment the time we have been idle on page, and let the server know it.
  idleCheck += (updateInterval/1000);
  cse[cseCount] = "i"+idleCheck;
  cseCount++;
  
  // iterate cseTriggersRun and delete any of the ID's stored
  // in the cseTriggers list.
  
  // first sort the array in reverse so we are always taking from the top
  // so indices dont get botched while we delete
  cseTriggersRun.sort(function(a, b) { return b - a; });  
  var tmpId=0;
  while(tmpId < cseTriggersRun.length) {
    cseTriggers.splice(cseTriggersRun[tmpId],1);
    cseTriggersCount--;
    tmpId++;
  }
  cseTriggersRun.length=0;
  
  // build string of trigger id's.
  var idList = '';
  for (var lcv = 0; lcv < cseTriggersCount; lcv++) {
      idList += cseTriggers[lcv] + "-";
  }
    
  // build string of events to send..
  var eventList = '';
  for(var lcv2 = 0; lcv2 < cseCount; lcv2++) {
    eventList += cse[lcv2]+'-';
  }
    
  var frmevtlist = '';
  if (cseFormCount > 0) {
	  frmevtlist = '<fes>';
	  for (var lcv3 = 0; lcv3 < cseFormCount; lcv3++) {
	      frmevtlist = frmevtlist + "<fe>" + cseForm + "</fe>";
	  }
	  frmevtlist += '</fes>';
  }
  
  // reset the event list counter.
  cseCount=0;
  cseFormCount=0;
  
  // tell the server the visitor denies a cobrowse request?
  var cobrowseResponse='';
  if (cobrowseDenied) {
      cobrowseResponse = "&cobrowse=no";
  } else {
      if (window.location.href.indexOf("cobrowse=end") != -1 && !endCobrowseProcessed) {
          cobrowseResponse = "&cobrowse=no";
          endCobrowseProcessed = true;
        }
  }
    
  imagePrimary.onload = primaryCheckReceived;
  imagePrimary.src = urlPrimaryCheck + '&ids=' + idList + '&evs=' + eventList + cobrowseResponse + "&cnt=" + timeSend() + "&fevs=" + frmevtlist;
}

// handle the result of the primary image check.
function primaryCheckReceived() {
    
    // get the width of the image returned..
    // 1x1 = nothing to do.  2x1 = need to iterate individually. 4x1 = cobrowse request
    var imgWidth;
    imgWidth = imagePrimary.width;  
    if(imgWidth==2) {
       
       // start the individual checking process with the first element in the
       // triggerID list.
       cseCheckingTrigger=0;
       triggerCheck();
       
    } 
    else 
    {
        if (imgWidth == 4) {
            cobrowseRequest();
        }
        else if (imgWidth == 7) {
            cobrowseRequest2();
        }
        else if (imgWidth == 5) {
            hideCurrentInvite();
        } else if (imgWidth == 6) {
            redirect();
        }
		
		// restart the timer, since there's nothing to do
		lfStartTimer();
	}  
	 
}

// initiate an update on the next trigger based on the index value
// stored in cseCheckingTrigger.
function triggerCheck() 
{
  imageTrigger.onload = triggerCheckReceived;    
  imageTrigger.src = urlTriggerCheck+'&tid='+cseTriggers[cseCheckingTrigger]+'&cnt='+timeSend();
}

// got an update on a check from a specific trigger.
// 1x1=fail and stop; 2x1=fail and continue; 3x1=execute and stop; 4x1=execute and continue
function triggerCheckReceived() 
{
    
    // get the width of the image returned..
    var imgWidth;
    imgWidth = imageTrigger.width;  
    
    // execute the trigger?
    if(imgWidth > 2) {	
        // by default erase the trigger.  the only exception is if it is an invite
        // that may be generated from an agent request.
        var eraseTrigger = true;
        
        // ok, so we know this triggerID needs to be run..
        // first we need to find it, becasue right now all we have is the index 
        // within the cseTriggers array.
        var id = cseTriggers[cseCheckingTrigger];
        
        // iterate the invites, actions, transactions.. if we have a match, run it.
        var lcv=0;
        while(lcv<contents.length) {
            if (id == contents[lcv].triggerID) {
                executeActionContent(contents[lcv]);
            }
            else {
                lcv++;
            }
        }
        
        // THIS CODE MUST BE RUN THIS WAY.  It look slike it could be optimized with combined If's but there
        // are timing issues that require the checks to be independent.
        lcv=0;
        var idToRun = -1;
        while(lcv<invites.length){
            if(id==invites[lcv].triggerID) 
            {                                
                idToRun = lcv;
                if (invites[idToRun].isAgentRequest) {
                    eraseTrigger = false;
                }
                if (!inviteDisplayed) {
                    executeActionInvite(invites[idToRun]);
                }
                break;
            }
            lcv++;            
        }                     
//        if(idToRun>-1) {
//            if(invites[idToRun].isAgentRequest)
//                eraseTrigger=false;
//            if(!inviteDisplayed)
//                executeActionInvite(invites[idToRun]);
//            
//        }
        
                        
        // alerts next... no such thing as non-clientside alerts
        lcv=0;
        while(lcv<alerts.length){
            if (id == alerts[lcv].triggerID) {
                executeActionAlert(alerts[lcv]);
            }
            else {
                lcv++;
            }
        }  
        
        // the trigger can only run once per-page load, so now remove the trigger
        // from the trigger list.
        if (eraseTrigger) {
            cseTriggersRun.push(cseCheckingTrigger);
        }
                 
    }
    
    // continue or stop? 2 and 4=continue so increase triggerIndex, and check next one
    if((imgWidth==2)||(imgWidth==4)) 
    {
      cseCheckingTrigger++;
      if(cseCheckingTrigger < cseTriggersCount)
      {
         triggerCheck();
      }
      else 
      {
         // stop checking invidual triggers, and start the primaryCheck again in 5 seconds.
         cseCheckingTrigger=0;
         lfStartTimer();
      }
    }
    else
    {
		lfStartTimer();
    }
}

// display an invite
function executeActionInvite(myInvite) 
{  
    // make sure the invite doesnt show again for displayInterval minutes
    var now2, diff2, diffAct;
	now2 = new Date();
	if(myInvite.displayInterval > 0) 
	{
      if (myInvite.displayedAt != null)
      {
        // invite was displayed previously
        diff2 = now2 - myInvite.displayedAt;  	  
	    diffAct = (diff2 / 1000 / 60); 
	    if (diffAct < myInvite.displayInterval) {
		  return;
	    }
      }
    }

    // Make Invite Div a child of the document body
    /*var body = document.body;
    if (divInvite.parentNode != body)
        setNewParent(divInvite, body);    */
    	
	myInvite.displayedAt = now2;
    
    // keep the current invite available to everyone.
    currentInvite = myInvite;
    
    // set up the div layer
    divInvite.style.width = myInvite.width + 'px';
    divInvite.style.height = myInvite.height + 'px';

    // set the original position of the invite based on the floatFrom
    // at this point
    getClientSize();
    switch(myInvite.floatFrom)
    {
        case enumNoFloat:
            // do not float - assume screen center            
            currentInvite.calculatedStartX = Math.round((clientWidth / 2) - (myInvite.width / 2));
            currentInvite.calculatedStartY = Math.round((clientHeight/ 2) - (myInvite.height / 2));
            break;    
		case enumTopLeft:
			currentInvite.calculatedStartX = -myInvite.width;
			currentInvite.calculatedStartY = -myInvite.height;
			break;
		case enumTop:
		    currentInvite.calculatedStartX = Math.round((clientWidth / 2) - (myInvite.width / 2));
			currentInvite.calculatedStartY = -myInvite.height;
			break;
		case enumTopRight:
			currentInvite.calculatedStartX = Math.round(clientWidth + myInvite.width);
			currentInvite.calculatedStartY = -myInvite.height;
			break; 
		case enumRight:
			currentInvite.calculatedStartX = Math.round(clientWidth + myInvite.width);
			currentInvite.calculatedStartY = Math.round((clientHeight / 2) - (myInvite.height / 2));
			break;
		case enumBottomRight:
			currentInvite.calculatedStartX = Math.round(clientWidth + myInvite.width);
			currentInvite.calculatedStartY = Math.round(clientHeight + myInvite.height);
			break;
		case enumBottom:
			currentInvite.calculatedStartX = Math.round((clientWidth / 2) - (myInvite.width / 2));
			currentInvite.calculatedStartY = Math.round(clientHeight + myInvite.height);
			break;
		case enumBottomLeft:
			currentInvite.calculatedStartX = -myInvite.width;
			currentInvite.calculatedStartY = Math.round(clientHeight + myInvite.height);
			break;
		case enumLeft:
			currentInvite.calculatedStartX = -myInvite.width;
			currentInvite.calculatedStartY = Math.round((clientHeight / 2) - (myInvite.height / 2));
			break;
		case enumCenter:
			currentInvite.calculatedStartX = Math.round((clientWidth / 2) - (myInvite.width / 2));
			currentInvite.calculatedStartY = Math.round((clientHeight / 2) - (myInvite.height / 2));
			break;
		case enumUseStartXYPos:
			currentInvite.calculatedStartX = myInvite.startX;
			currentInvite.calculatedStartY = myInvite.startY;
			break;
    }  
    
    divInvite.style.left = currentInvite.calculatedStartX + 'px';
    divInvite.style.top = currentInvite.calculatedStartY + 'px'; 
    
    // now adjust for the size of the box.. 
    //if((myInvite.floatFrom != enumNoFloat) && (myInvite.floatFrom != enumUseStartXYPos)) {        
        window.onresize=setupFloat;
	    window.onscroll=adjustFloat;
    //}
        
    // redirect the iframe to the proper page that shows the invite..
    if (browser.isSafari) {
        iframeInvite.src = urlInvite + "&id=" + myInvite.inviteID + "&tid=" + myInvite.triggerID + "&cnt=" + timeSend();
    } else {
        iframeInvite.setAttribute("src", urlInvite + "&id=" + myInvite.inviteID + "&tid=" + myInvite.triggerID + "&cnt=" + timeSend());
    }   
    
    // remove invite from lists
    if((myInvite.triggerID>0)&&(!myInvite.isAgentRequest)) {
      var index = -1;
      for (var lcv = 0; lcv < invites.length; lcv++) {
          if (invites[lcv].triggerID == myInvite.triggerID) {
              index = lcv; break; 
          }
      }
      if (index > -1) {
          invites.splice(index, 1); 
      }
    }
    
    // show the invite..
    floatX=10;
    floatY=10;
    ifloatX=floatX;
    ifloatY=floatY;
    currentInvite.displayedAt = new Date();  // reset the display time to now
    //if (myInvite.floatTo != enumNoFloat) {
        setTimeout("StartInviteMove()", 500);        
    //}
    
    // now make sure the div is visible
    divInvite.style.display = "inline";
    inviteDisplayed = true;    
}

function StartInviteMove() {
    setupFloat();
    lastX = -1;
    lastY = -1;
    adjustFloat();
}

// used to get the current window height and width..
function getWindowWidth() {
 if ((browser.isNS4x) || (browser.isNS6up))
    return window.innerWidth;
 else
    return document.documentElement.offsetWidth;
}
function getWindowHeight() {
    if ((browser.isNS4x) || (browser.isNS6up)) {
        return window.innerHeight;
    }
    else {
        return document.documentElement.offsetHeight;
    }
}

// hide currently displayed invite.
function hideCurrentInvite() {

   divInvite.style.display = 'none';
   
   // redirect the url within the div to nothing.
   iframeInvite.src = 'about:blank';
   
   // tell everyone else no invite is displayed.
   inviteDisplayed=false;

}

// force redirect to new page
function redirect() {
    window.location = urlRedirect;
}

  

function adjustFloat() {   
    if(inviteDisplayed) {
		
		if (currentInvite.displaySeconds > 0)
		{
			var now, diff;
			now = new Date();
			diff = now - currentInvite.displayedAt;  // diff in milliseconds
			if ((diff / 1000) >= currentInvite.displaySeconds)
			{
				return hideCurrentInvite();
			}
        }
        if ((currentInvite.floatFrom == enumNoFloat) || (currentInvite.floatFrom == enumUseStartXYPos)) {
        
            // do nothing here, we are not floating.  but we still needed the above code to make the invite go away, if necessary
            
        }
        else {
            if ((NS4) || (NS6)) {
                if (lastX == -1 || delayspeed == 0) {
                    lastX = window.pageXOffset + currentInvite.calculatedStartX;
                    lastY = window.pageYOffset + currentInvite.calculatedStartY;
                }
                else {
                    var dx = Math.abs(window.pageXOffset + floatX - lastX);
                    var dy = Math.abs(window.pageYOffset + floatY - lastY);
                    var d = Math.sqrt(dx * dx + dy * dy);
                    var c = Math.round(d / 10);
                    if (window.pageXOffset + floatX > lastX) { lastX = lastX + delayspeed + c; }
                    if (window.pageXOffset + floatX < lastX) { lastX = lastX - delayspeed - c; }
                    if (window.pageYOffset + floatY > lastY) { lastY = lastY + delayspeed + c; }
                    if (window.pageYOffset + floatY < lastY) { lastY = lastY - delayspeed - c; }
                }
                if (NS4) {
                    document.layers['lf_div_invite'].pageX = lastX;
                    document.layers['lf_div_invite'].pageY = lastY;
                    document.layers['lf_div_invite'].style.zIndex = 99;
                }
                if (NS6) {
                    document.getElementById('lf_div_invite').style.left = lastX + 'px';
                    document.getElementById('lf_div_invite').style.top = lastY + 'px';
                    document.getElementById('lf_div_invite').style.zIndex = 99;
                }
            }
            else if (IE4) {
                if (lastX == -1 || delayspeed == 0) {
                    lastX = getScrollLeft() + currentInvite.calculatedStartX; // floatX;
                    lastY = getScrollTop() + currentInvite.calculatedStartY; // floatY;
                }
                else {
                    var dx = Math.abs(getScrollLeft() + floatX - lastX);
                    var dy = Math.abs(getScrollTop() + floatY - lastY);
                    var d = Math.sqrt(dx * dx + dy * dy);
                    var c = Math.round(d / 10);
                    if (getScrollLeft() + floatX > lastX) { lastX = lastX + delayspeed + c; }
                    if (getScrollLeft() + floatX < lastX) { lastX = lastX - delayspeed - c; }
                    if (getScrollTop() + floatY > lastY) { lastY = lastY + delayspeed + c; }
                    if (getScrollTop() + floatY < lastY) { lastY = lastY - delayspeed - c; }
                }
                //            document.all['lf_div_invite'].style.posLeft = lastX;
                //            document.all['lf_div_invite'].style.posTop = lastY;
                document.all['lf_div_invite'].style.left = lastX + 'px';
                document.all['lf_div_invite'].style.top = lastY + 'px';
                document.all['lf_div_invite'].style.zIndex = 99;
            }
        }
       setTimeout(function() { adjustFloat(); }, 50);
    }
}

function getClientSize() 
{
	clientWidth = 0;
	clientHeight = 0;
	if( typeof( window.innerWidth ) == 'number' ) 
	{
		//Non-IE
		clientWidth = window.innerWidth;
		clientHeight = window.innerHeight;
	}
	else if ( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) 
	{
		//IE 6+ in 'standards compliant mode'
		clientWidth = document.documentElement.clientWidth;
		clientHeight = document.documentElement.clientHeight;
	} 
	else if ( document.body && (document.body.offsetHeight || document.body.offsetWidth ) )
	{
		clientHeight = document.body.offsetHeight;
		clientWidth = document.body.offsetWidth;
	}	
	else if (document.body && ( document.body.clientWidth || document.body.clientHeight ) )
	{
		//IE 4 compatible
		clientWidth = document.body.clientWidth;
		clientHeight = document.body.clientHeight;
	}
}
function setupFloat() {

    if ((currentInvite.floatFrom == enumNoFloat) || (currentInvite.floatFrom == enumUseStartXYPos)) {
        // do nothing here
        return;
    }
      
      // for easy reference.
      var layerwidth=currentInvite.width;
      var layerheight=currentInvite.height;
      getClientSize();
  
      // find the resting location of the inite.
      var halign="center";
      var valign="center";

      if ((currentInvite.floatTo == enumTopLeft) ||
         (currentInvite.floatTo == enumLeft) ||
         (currentInvite.floatTo == enumBottomLeft)) {
          halign = "left";
      }
      if ((currentInvite.floatTo == enumTopRight) ||
         (currentInvite.floatTo == enumRight) ||
         (currentInvite.floatTo == enumBottomRight)) {
          halign = "right";
      }
      if ((currentInvite.floatTo == enumTopLeft) ||
         (currentInvite.floatTo == enumTop) ||
         (currentInvite.floatTo == enumTopRight)) {
          valign = "top";
      }
      if ((currentInvite.floatTo == enumBottomLeft) ||
         (currentInvite.floatTo == enumBottom) ||
         (currentInvite.floatTo == enumBottomRight)) {
          valign = "bottom";
      }
           
    if ((NS4) || (NS6)) {
		switch(halign)
		{
			case "left":
				floatX = ifloatX;
				break;
			case "right":
				floatX = clientWidth - ifloatX - layerwidth;
				break;
			case "center":
				floatX = Math.round((clientWidth/2)-(layerwidth/2));
				break;
		}
		switch(valign)
		{
			case "top":
				floatY = ifloatY;
				break;
			case "bottom":
				//floatY = clientHeight - ifloatY - layerheight;
				floatY = clientHeight - layerheight;
				break;
			case "center":
				floatY = Math.round((clientHeight/2) - (layerheight/2))+50;												
				break;
		}
    }
    else
    {
		switch(halign)
		{
			case "left":
				floatX = ifloatX;
				break;
			case "right":
				//floatX = document.body.offsetWidth-ifloatX-layerwidth;
				floatX = clientWidth - ifloatX - layerwidth;
				break;
			case "center":
				floatX = Math.round((clientWidth/2)-(layerwidth/2));
				break;
		}
		switch(valign)
		{
			case "top":
				floatY = ifloatY;
				break;
			case "bottom":
				//floatY = document.body.offsetHeight-ifloatY-layerheight;
				//floatY = clientHeight-ifloatY-layerheight;
				floatY = clientHeight - layerheight;
				break;
			case "center":
				floatY = Math.round((clientHeight/2)-(layerheight/2))+50;				
				break;
		}
    }
}

// change some content
function executeActionContent(myContent) {

    if (myContent.isJavascript) {
        eval(myContent.content);
    }
    else {
    
        // first find the object in the dom
        var obj = getObjectId(myContent.elementID);
        
        // try setting the innerhtml of that object.
        // then interate the styles..
        if (obj != null) {
            if ((myContent.content != null) && (myContent.content != '')) {
                obj.innerHTML = decodeHTML(myContent.content);
            }
		    for (var lcv = 0; lcv < myContent.styles.styleCount; lcv++) {
		        var curStyle = myContent.styles.styleList[lcv];
		        if (curStyle.styleIsProperty) {
		            obj.setAttribute(curStyle.styleID, curStyle.styleValue);
		        }
		        else {
		            setStyle(obj, curStyle.styleID, curStyle.styleValue);  //obj.style[curStyle.styleID] = curStyle.styleValue;
		        }
		    }
		}       
    }
    
    // remove content change from lists...
    if(myContent.triggerID>0) {
      var index = -1;
      for (var lcv = 0; lcv < contents.length; lcv++) {
          if (contents[lcv].triggerID == myContent.triggerID) { index = lcv; break; }
      }
      if (index > -1) { contents.splice(index, 1); }
    }
}

function decodeHTML(enc){
  enc=enc.replace(/&gt;/g,'>').replace(/&lt;/g,'<').replace(/&quot;/g,'"').replace(/&amp;/g,'&');
  return enc.replace(/&apos;/g,"'");
}

function setStyle(objId, styleId, value){
   getRef(objId).style[styleId]= value;
}
function getRef(obj){
		return (typeof obj == "string") ?
			 document.getElementById(obj) : obj;
}

// execute alert.. really just take it out of the list.
function executeActionAlert(myAlert) {

    // remove alert from list..
    if(myAlert.triggerID>0) {
      var index = -1;
      for (var lcv = 0; lcv < alerts.length; lcv++) {
          if (alerts[lcv].triggerID == myAlert.triggerID) { index = lcv; break; } 
      }
      if (index > -1) { alerts.splice(index, 1); }
    }
}

// execute on a cobrowse request from an agent..
function cobrowseRequest() {    
    if(!cobrowseRequestPending) {
     cobrowseRequestPending=true;
     if(confirm(msgCobrowseRequest)) {
         if ((String(top.document.location).toLowerCase().indexOf('https') == 0) &&
          (urlCobrowse.toLowerCase().indexOf('https') != 0)) { urlCobrowse = 'https' + urlCobrowse.substring(4); }
         else if ((String(top.document.location).toLowerCase().indexOf('https') == -1) &&
               (urlCobrowse.toLowerCase().indexOf('https') == 0)) { urlCobrowse = 'http' + urlCobrowse.substring(5); }
       top.document.location = urlCobrowse;
     } 
     else {
       cobrowseDenied = true;
       cobrowseRequestPending = false;
     }
    }
}

// execute on a cobrowse request from an agent..
function cobrowseRequest2() {
    if (!cobrowseRequestPending) {
        cobrowseRequestPending = true;
        if (confirm(msgCobrowseRequest)) {
            top.document.location = CobrowseUrlBase +
                top.document.location.host +
                top.document.location.pathname +
                top.document.location.search +
                top.document.location.hash;
        }
        else {
            cobrowseDenied = true;
            cobrowseRequestPending = false;
        }
    }
}

// constructor for browser information
function VBrowserDetect() {
   var ua = navigator.userAgent.toLowerCase(); 
   this.isGecko       = (ua.indexOf('gecko') != -1 && ua.indexOf('safari') == -1);
   this.isAppleWebKit = (ua.indexOf('applewebkit') != -1);
   this.isKonqueror   = (ua.indexOf('konqueror') != -1); 
   this.isSafari      = (ua.indexOf('safari') != - 1);
   this.isOmniweb     = (ua.indexOf('omniweb') != - 1);
   this.isOpera       = (ua.indexOf('opera') != -1); 
   this.isIcab        = (ua.indexOf('icab') != -1); 
   this.isAol         = (ua.indexOf('aol') != -1); 
   this.isIE          = (ua.indexOf('msie') != -1 && !this.isOpera && (ua.indexOf('webtv') == -1) ); 
   this.isMozilla     = (this.isGecko && ua.indexOf('gecko/') + 14 == ua.length);
   this.isFirebird    = (ua.indexOf('firebird/') != -1);
   this.isNS          = ( (this.isGecko) ? (ua.indexOf('netscape') != -1) : ( (ua.indexOf('mozilla') != -1) && !this.isOpera && !this.isSafari && (ua.indexOf('spoofer') == -1) && (ua.indexOf('compatible') == -1) && (ua.indexOf('webtv') == -1) && (ua.indexOf('hotjava') == -1) ) );
   this.isIECompatible = ( (ua.indexOf('msie') != -1) && !this.isIE);
   this.isNSCompatible = ( (ua.indexOf('mozilla') != -1) && !this.isNS && !this.isMozilla);
   this.geckoVersion = ( (this.isGecko) ? ua.substring( (ua.lastIndexOf('gecko/') + 6), (ua.lastIndexOf('gecko/') + 14) ) : -1 );
   this.equivalentMozilla = ( (this.isGecko) ? parseFloat( ua.substring( ua.indexOf('rv:') + 3 ) ) : -1 );
   this.appleWebKitVersion = ( (this.isAppleWebKit) ? parseFloat( ua.substring( ua.indexOf('applewebkit/') + 12) ) : -1 );
   this.versionMinor = parseFloat(navigator.appVersion); 
   if (this.isGecko && !this.isMozilla) {
      this.versionMinor = parseFloat( ua.substring( ua.indexOf('/', ua.indexOf('gecko/') + 6) + 1 ) );
   }
   else if (this.isMozilla) {
      this.versionMinor = parseFloat( ua.substring( ua.indexOf('rv:') + 3 ) );
   }
   else if (this.isIE && this.versionMinor >= 4) {
      this.versionMinor = parseFloat( ua.substring( ua.indexOf('msie ') + 5 ) );
   }
   else if (this.isKonqueror) {
      this.versionMinor = parseFloat( ua.substring( ua.indexOf('konqueror/') + 10 ) );
   }
   else if (this.isSafari) {
      this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('safari/') + 7 ) );
   }
   else if (this.isOmniweb) {
      this.versionMinor = parseFloat( ua.substring( ua.lastIndexOf('omniweb/') + 8 ) );
   }
   else if (this.isOpera) {
      this.versionMinor = parseFloat( ua.substring( ua.indexOf('opera') + 6 ) );
   }
   else if (this.isIcab) {
      this.versionMinor = parseFloat( ua.substring( ua.indexOf('icab') + 5 ) );
   }   
   this.versionMajor = parseInt(this.versionMinor); 
   this.isDOM1 = (document.getElementById);
   this.isDOM2Event = (document.addEventListener && document.removeEventListener);
   this.mode = document.compatMode ? document.compatMode : 'BackCompat';
   this.isWin    = (ua.indexOf('win') != -1);
   this.isWin32  = (this.isWin && ( ua.indexOf('95') != -1 || ua.indexOf('98') != -1 || ua.indexOf('nt') != -1 || ua.indexOf('win32') != -1 || ua.indexOf('32bit') != -1 || ua.indexOf('xp') != -1) );
   this.isMac    = (ua.indexOf('mac') != -1);
   this.isUnix   = (ua.indexOf('unix') != -1 || ua.indexOf('sunos') != -1 || ua.indexOf('bsd') != -1 || ua.indexOf('x11') != -1)
   this.isLinux  = (ua.indexOf('linux') != -1);
   this.isNS4x = (this.isNS && this.versionMajor == 4);
   this.isNS40x = (this.isNS4x && this.versionMinor < 4.5);
   this.isNS47x = (this.isNS4x && this.versionMinor >= 4.7);
   this.isNS4up = (this.isNS && this.versionMinor >= 4);
   this.isNS6x = (this.isNS && this.versionMajor == 6);
   this.isNS6up = (this.isNS && this.versionMajor >= 6);
   this.isNS7x = (this.isNS && this.versionMajor == 7);
   this.isNS7up = (this.isNS && this.versionMajor >= 7);
   this.isIE4x = (this.isIE && this.versionMajor == 4);
   this.isIE4up = (this.isIE && this.versionMajor >= 4);
   this.isIE5x = (this.isIE && this.versionMajor == 5);
   this.isIE55 = (this.isIE && this.versionMinor == 5.5);
   this.isIE5up = (this.isIE && this.versionMajor >= 5);
   this.isIE6x = (this.isIE && this.versionMajor == 6);
   this.isIE6up = (this.isIE && this.versionMajor >= 6);   
   this.isIE4xMac = (this.isIE4x && this.isMac);
}

// setup generic methods for accessing DOM and hooking into events
function getObjectId(idOfObject) {
    if (document.getElementById)
        var returnVar = document.getElementById(idOfObject);
    else if (document.all)
        var returnVar = document.all[idOfObject];
    else if (document.layers)
        var returnVar = document.layers[idOfObject];
    return returnVar; 
}
function findDOMObject(idOfObject) {
	for (var i = 0; i < document.images.length; i++) {
		if (document.images[i].id==idOfObject || document.images[i].name==idOfObject) return document.images[i]
	}
	return document.getElementById(idOfObject)
}
function findLayer(node,idOfObject) {
    if (node.id == idOfObject || node.name == idOfObject) { Obj = node; }
	for ( var counter = 0; counter < node.document.images.length; counter++ ) {
		if (node.document.images[counter].id==idOfObject || node.document.images[counter].name==idOfObject) Obj = node.document.images[counter];
	}
	for ( var counter = 0; counter < node.document.forms.length; counter++ ) {
	    if (node.document.forms[counter].id == idOfObject || node.document.forms[counter].name == idOfObject) { Obj = node.document.forms[counter]; }
		for ( var i = 0; i < node.document.forms[counter].elements.length; i++) {
			if (node.document.forms[counter].elements[i].id==idOfObject || node.document.forms[counter].elements[i].name==idOfObject ) Obj = node.document.forms[counter].elements[i];
		}
	}
	for ( var i = 0; i < node.document.layers.length; i++ ) {
		findLayer(node.document.layers[i],idOfObject);
	}
}
function EventAttacher(event, pdisp)
{
	eval('this.' + event + ' = ' + pdisp);
	if (this.captureEvents) {
	    this.captureEvents(eval('Event.' + event.substr(2)));
	}
}
function velaro_addEvent(obj, evType, fn){
  if (obj.addEventListener){
    obj.addEventListener(evType, fn, false);
    return true;
  } else if (obj.attachEvent){
    var r = obj.attachEvent("on"+evType, fn);
    return r;
  } else {
    //alert("Handler could not be attached");
  }
}
function velaro_captureEvent(event)
{
	var obj = event.currentTarget ? event.currentTarget : event.srcElement;
	var params = '';
	switch(event.type)
	{
	    case 'blur':
	    case 'change':
			// for textboxes/areas when they lose focus
			if (obj.form != null)
			{
				if (obj.selectedIndex)
				{
					params = "<f>" + obj.form.id + "</f><e>" + obj.id + "</e><v>" + obj[obj.selectedIndex].text + "</v>";
				}
				else
				{
					if (obj.noChange) return; //prevent duplicates
					params = "<f>" + obj.form.id + "</f><e>" + obj.id + "</e><v>" + obj.value + "</v>";
				}
			}
	        break;
	    case 'keyup':
			// not used at the moment...
            if (obj.noChange) return; //prevent duplicates
            if (obj.form != null)
            {
				params = "<f>" + obj.form.id + "</f><e>" + obj.id + "</e><v>" + obj.value + "</v>";
			}
	        break;
	    case 'click':
			// for radio buttons and checkbox values changing
            if (obj.noClick) return; //prevent duplicates
	        if (obj.type == 'radio' || obj.type == 'checkbox')
	        {
	            params = "<f>" + obj.form.id + "</f><e>" + obj.id + "</e><v>" + obj.checked + "</v>";
	        }	        
            break;
	}
	
	// queue up the form event
	if ((params != null) && (params != ''))
	{
		cseForm[cseFormCount] = params;
		cseFormCount++;
	}
}
function velaro_copyEvent(event)
{
	var obj = event.currentTarget ? event.currentTarget : event.srcElement;
    if (obj.noClick) return; //prevent duplicates
	var params = event.type;
	var action = "event";
	var frameName = obj ? obj.frameName : '';
    //velaro_GetXMLText(action, obj ? (obj.id ? 'id:' + obj.id : (obj.name && document.getElementsByName(obj.name).length == 1 ? 'name:' + obj.name : 'index:' + obj.documentIndex)) : null, params, frameName);
}

function HandleResize()
{
	location.reload();
	return false;
}
function assignLocalHandlers() {
    if(document.getElementById == null) {
        document.getElementById = getObjectId;
    }
    if (window.attachEvent == null)
    {
	    document.attachEvent = window.attachEvent = EventAttacher;
    	
	    if (document.getElementsByTagName != null)
		    allElements = document.getElementsByTagName('*');
	    else if (document.all)
		    allElements = document.all;
	    else
		    allElements = document.forms[0].elements;

	    for (i = 0; i < allElements.length; i++)
	    {
		    allElements[i].attachEvent = EventAttacher;
				
			// attach event handlers to form controls, but don't attach
			// to nuthin' that isn't in a form
			if ( (allElements[i].form != null) && (allElements[i].id != '') )
			{
				switch(allElements[i].tagName)
				{
					case 'INPUT':
						switch (allElements[i].type)
						{
							case 'text':
								velaro_addEvent(allElements[i], "blur", velaro_captureEvent);
								break;
							case 'checkbox':
							case 'radio':
								velaro_addEvent(allElements[i], "click", velaro_captureEvent);
								break;
						}
						break;
					case 'TEXTAREA':
						velaro_addEvent(allElements[i], "blur", velaro_captureEvent);
						break;
					case 'SELECT':
						velaro_addEvent(allElements[i], "change", velaro_captureEvent);
						break;
				}
			}
		}
    }
    if (browser.isNS4x)
    {
	    window.captureEvents(Event.RESIZE);
	    window.onresize = HandleResize;
    }      
}


// iterate all the actions, if any require hooks in to the 
// local events, then hook.. otherwise don't.
function setupClientSideEvents() {   
    var clientSideEventsRequired=false;
    for(lcv=0;lcv<invites.length;lcv++)
      if(invites[lcv].clientSideEvents) clientSideEventsRequired=true;
    for(lcv=0;lcv<contents.length;lcv++)
      if(contents[lcv].clientSideEvents) clientSideEventsRequired=true;
    for(lcv=0;lcv<alerts.length;lcv++)
      if(alerts[lcv].clientSideEvents) clientSideEventsRequired=true; 
    return clientSideEventsRequired; 
}

function timeSend() {
  var ndate = new Date(); 
  return ndate.getTime();
}

function createElement(element) {
	if (typeof document.createElementNS != 'undefined') {
		return document.createElementNS('http://www.w3.org/1999/xhtml', element);
	}
	if (typeof document.createElement != 'undefined'){
		return document.createElement(element);
	}
	return false;
}

function setNewParent(el, newParent) {
    newParent.appendChild(el);
}

function arrayContains(arry, compareTo) {
    for (var i = 0; i < arry.length; i++) {
        if (arry[i] == compareTo) {
            return true;
        }
    }
    return false;
}

function getScrollTop() {
    var offsetY;
    //strict mode
    if (!(document.documentElement.scrollTop == 0)) {
        offsetY = document.documentElement.scrollTop;
    }
    //quirks mode
    else {
        offsetY = document.body.scrollTop;
    }

    return offsetY;
}

function getScrollLeft() {
    var offsetX;
    //strict mode
    if (!(document.documentElement.scrollTop == 0)) {
        offsetX = document.documentElement.scrollLeft;
    }
    //quirks mode
    else {
        offsetX = document.body.scrollLeft;
    }

    return offsetX;
}

function lfDebug(obj) {
    if ('undefined' != typeof console) {
        var d = ((new Date().getTime()) - LFStartTime);
        console.log("%o", obj + " : " + d + "ms");
    }
}
