/* 
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
*/
//
// shared.js
//


// -------------------------------------------------------------------------------------

function inUndefined(o) { return (typeof o == "undefined"); }
function isBoolean(b) { return (typeof b == "boolean"); }
function isString(s) { return (typeof s == "string"); }
function isNumber(n) { return (typeof n == 'number' && isFinite(n)); }

// -------------------------------------------------------------------------------------

function GetIsIE() 
{
    var isIE = (navigator.appName.indexOf("Microsoft") != -1);
    return isIE;
}

function GetIEversion(){ // subset of GetIEinfo func returns correct ie version 
	
	var _n=navigator,_w=window,_d=document;
	var version="NA";
	var na=_n.userAgent;
	//var ieDocMode="NA";
	var ie8BrowserMode="NA";
	
	// Look for msie and make sure its not opera in disguise
	if(/msie/i.test(na) && (!_w.opera)){
		// also check for spoofers by checking known IE objects
		if(_w.attachEvent && _w.ActiveXObject){		
			// Get version displayed in UA although if its IE 8 running in 7 or compat mode it will appear as 7
			version = (na.match( /.+ie\s([\d.]+)/i ) || [])[1];
			// Its IE 8 pretending to be IE 7 or in compat mode		
			if(parseInt(version)==7){				
				// documentMode is only supported in IE 8 so we know if its here its really IE 8
				if(_d.documentMode){
					version = 8; //reset? change if you need to
					// IE in Compat mode will mention Trident in the useragent
					if(/trident\/\d/i.test(na)){
						ie8BrowserMode = "Compat Mode";
					// if it doesn't then its running in IE 7 mode
					}else{
						ie8BrowserMode = "IE 7 Mode";
					}
				}
			}else if(parseInt(version)==8){
				// IE 8 will always have documentMode available
				if(_d.documentMode){ ie8BrowserMode = "IE 8 Mode";}
			}
			// If we are in IE 8 (any mode) or previous versions of IE we check for the documentMode or compatMode for pre 8 versions			
			//ieDocMode = (_d.documentMode) ? _d.documentMode : (_d.compatMode && _d.compatMode=="CSS1Compat") ? 7 : 5;//default to quirks mode IE5				   			
		 }
	}
			//alert('version ' + version);	 
	return {
		
		//"Version" : version,

	}			
}

function GetIEinfo(){ // gets all ie info
	
	var _n=navigator,_w=window,_d=document;
	var version="NA";
	var na=_n.userAgent;
	var ieDocMode="NA";
	var ie8BrowserMode="NA";
	
	// Look for msie and make sure its not opera in disguise
	if(/msie/i.test(na) && (!_w.opera)){
		// also check for spoofers by checking known IE objects
		if(_w.attachEvent && _w.ActiveXObject){		
			// Get version displayed in UA although if its IE 8 running in 7 or compat mode it will appear as 7
			version = (na.match( /.+ie\s([\d.]+)/i ) || [])[1];
			// Its IE 8 pretending to be IE 7 or in compat mode		
			if(parseInt(version)==7){				
				// documentMode is only supported in IE 8 so we know if its here its really IE 8
				if(_d.documentMode){
					version = 8; //reset? change if you need to
					// IE in Compat mode will mention Trident in the useragent
					if(/trident\/\d/i.test(na)){
						ie8BrowserMode = "Compat Mode";
					// if it doesn't then its running in IE 7 mode
					}else{
						ie8BrowserMode = "IE 7 Mode";
					}
				}
			}else if(parseInt(version)==8){
				// IE 8 will always have documentMode available
				if(_d.documentMode){ ie8BrowserMode = "IE 8 Mode";}
			}
			// If we are in IE 8 (any mode) or previous versions of IE we check for the documentMode or compatMode for pre 8 versions			
			ieDocMode = (_d.documentMode) ? _d.documentMode : (_d.compatMode && _d.compatMode=="CSS1Compat") ? 7 : 5;//default to quirks mode IE5				   			
		 }
	}
			//alert('docmode ' +ieDocMode + ', browsermode ' + ie8BrowserMode + ', version ' + version);	 
	//return {
		
		//"UserAgent" : na,
		//"Version" : version,
		//"BrowserMode" : ie8BrowserMode,
		//"DocMode": ieDocMode
	//}			
}



function disabletext(e){
    return false
}

function reEnable(){
    return true
}

function GetCurrentDateTimeString() 
{
    var d = new Date();
    return d.getFullYear() + "-" + (d.getMonth()+1) + "-" + d.getDate()  + " " + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + "." + d.getMilliseconds();
}

function customHandler(desc,page,line,chr)  
{
    if(document.readyState != "complete") return true;
    
    alert('JavaScript error occurred! \n' +
          'The error was handled by ' +
          'a customized error handler (see shared.js).' +
          '\nError description: ' + desc +
          '\nPage address:      ' + page +
          '\nLine number:       ' + line);
    return true;
}
//window.onerror=customHandler;

//if the browser is IE4+
//document.onselectstart=new Function ("return false")

//if the browser is NS6
//if (window.sidebar){
//    document.onmousedown=disabletext
//    document.onclick=reEnable
//}


/*
Makes sync request to the server page
url - is a url for the server page
method - "GET" or "POST"
postdata - postdata to be passed to the server page
return page response as text
*/
function ExecServerRequest(url, method, postdata)
{
    if(method == null) method = "GET";
    if(postdata == null) postdata = "";
    
    var xmlHttp = null;
    var r = "";
	if(window.XMLHttpRequest)
		xmlHttp = new XMLHttpRequest();
    
	if(xmlHttp == null)
		xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    	
    if(xmlHttp == null)
	    alert('Unable to allocate server request object.');
	    
    xmlHttp.open(method, url, false);
    xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

    window.status = "Sending request...";
    xmlHttp.send(postdata);
    window.status ="Processing response...";

    r = xmlHttp.responseText;
    
    xmlHttp = null;
    if(r.length == 0)
        window.status = "Error";
    else
        window.status = "";
    return r;
}

function XBrowserAddHandler(target,eventName,handlerName) 
{ 
    if ( target.addEventListener ) 
    { 
        target.addEventListener(eventName, function(e){target[handlerName](e);}, false);
    } 
    else if ( target.attachEvent ) 
    { 
        target.attachEvent("on" + eventName, function(e){target[handlerName](e);});
    } 
    else 
    { 
        var originalHandler = target["on" + eventName]; 
        if ( originalHandler ) 
        { 
            target["on" + eventName] = function(e){originalHandler(e);target[handlerName](e);}; 
        } 
        else 
        { 
            target["on" + eventName] = target[handlerName]; 
        } 
    } 
}



function OnEnterOrEsc(evt, controlId)
{
    var code;
    if(evt.charCode)
        code = evt.charCode;
    else
        code = evt.keyCode;

    if(code == 27 || code == 13)
    {
    	if(evt.stopPropagation)
    	    evt.stopPropagation();
    	else
    	    evt.returnValue = false;
    }
    
    switch(code)
    {
        case 27: __doPostBack(evt, controlId, "ESC");break;
        case 13: __doPostBack(evt, controlId, "ENTER");break;
    }        
}

// BEGIN: Body resizing.

var _windowWidth;
var _windowHeight;

var _difWidth = 0;
var _difHeight = 0;


function body_Resize()
{
    var w = GetWindowWidth();
    var h = GetWindowHeight();

    _difWidth = w - _windowWidth;
    _difHeight = h - _windowHeight;
}

function body_Load()
{
    _windowWidth = GetWindowWidth();
    _windowHeight = GetWindowHeight();

    body_Resize();
}

// END: Body resizing.

function SetContainerKeyPressEvent(buttonId)
{
    window.setTimeout("SetContainerKeyPressEventDelayed('" + buttonId + "')", 100);
}

function SetContainerKeyPressEventDelayed(buttonId)
{
	var btn = document.getElementById(buttonId)
	if(btn != null)
	{
        var container = btn.parentNode;
        while(container != null && container.getAttribute("defaultcontainer") == null)
	        container = container.parentNode;
        	
        if(container == null || container.getAttribute("defaultcontainer") == null)
        {
	        alert("Unable to find default container for default button '" + buttonId + "'");
	        return;
        }

        var evtstr = container.onkeypress;
        if(!(evtstr != null))
        {
            if ( container.addEventListener ) 
            { 
                container.setAttribute("onkeypress", "return OnEnterKeyPress(event, '" + buttonId + "');");
                //container.addEventListener("keypress", function(e){ return OnEnterKeyPress(e, buttonId);}, false);
            } 
            else if ( container.attachEvent ) 
            { 
                container.attachEvent("onkeypress", function(e){ return OnEnterKeyPress(e, buttonId);});
            } 
        }
    }
}

function OnEnterKeyPress(evt, controlId)
{
    var code;
    if(evt.charCode)
        code = evt.charCode;
    else
        code = evt.keyCode;

    switch(code)
    {
        case 13: 
            var btn = document.getElementById(controlId);
            if(btn.click)
				btn.click();
            else
            {
                var f = btn.onclick + "";
                f += "onclick(evt);";
                eval(f);
            }
            break;
    }        
    
    if(code == 13)
        return false;
        
    return true;
}

//Function will show/hide any div on the page with the id = elementId
//when the user performs a ctrl + left mouse click
//EX.  Add [onmousedown="showHiddenDiv('_hiddenDiv');"] to the Div the user can ctrl+click on.
//Any Div with the id of '_hiddenDiv' will have their visibility flipped.
function showHiddenDiv(elementId)
{
	if(event.ctrlKey == true)
	{
		var divCollection = document.getElementsByTagName("div");
		for (var i=0; i<divCollection.length; i++) {
			if(divCollection[i].getAttribute("id") == elementId) {
				if(divCollection[i].style.display == 'block')
				{
					divCollection[i].style.display = 'none';
				}
				else
				{
					divCollection[i].style.display = 'block';
				}
			}
		}
	}

}






var _windowToPrint;

function PrintControl(controlId, title)
{
    var w = null;
    try
    {
        var c = document.getElementById(controlId);
        if(c != null)
        {
            w = window.open("about:blank", "printing", "width=1px, height=1px");
            var str = new String();
            str += "<html><head>";
            str += document.childNodes[0].childNodes[0].innerHTML;
            str += "</head><body>";
            str += c.innerHTML;
            str += "</body></html>";
            w.document.write(str);
            w.document.title = title;
            w.document.close();
            _windowToPrint = w;
            window.setTimeout("PrintWindow();", 250);
        }
    }
    catch(e)
    {
        alert("Error printing control '" + controlId + "'. Error message: " + e);
    }
}

function PrintWindow()
{
    if(_windowToPrint == null) return;
    
    if(_windowToPrint.document.readyState == "complete")
    {
        _windowToPrint.print();
        _windowToPrint.close();
    }
    else
    {
        window.setTimeout("PrintWindow();", 250);
    }
}

            
XBrowserAddHandler(window, "load", "body_Load");
XBrowserAddHandler(window, "resize", "body_Resize");

//
// This function is used to scale down images to fit within a 
// max height and width.  
//
//	imageId = the id of the image element (ClientId)
//	maxHeight = the max height in pixels
//	maxWidth = the max width in pixels
//
function ShrinkSizeOfImage(imageId, maxHeight, maxWidth) 
{
	return;
	var image = document.getElementById(imageId);
	if (! image) 
		alert("ShrinkSizeOfImage(): Image Not Found: |" + imageId + "|");
		
	//alert("maxHeight=|" + maxHeight + "| height=|" + image.height + "| maxWidth=|" + maxWidth + "| width=|" + image.width + "|");
	
	var height = image.height;
	var width = image.width;
	
	if ( maxHeight && (maxHeight > 0) && (height > maxHeight) )
	{
		var factor = (maxHeight / height);
		var newHeight = height * factor;
		var newWidth = width * factor;

		//alert("Height adjustment [" + maxHeight + "]: width: |" + width + "->" + newWidth + "| height: |" + height + "->" + newHeight + "|");
		image.width = newWidth;
		image.height = newHeight;
	}


	height = image.height;
	width = image.width;
	
	if ( maxWidth && (maxWidth > 0) && (width > maxWidth) )
	{
		var factor = (maxWidth / width);
		var newHeight = height * factor;
		var newWidth = width * factor;

		//alert("Width adjustment [" + maxWidth + "]: width: |" + width + "->" + newWidth + "| height: |" + height + "->" + newHeight + "|");
		image.width = newWidth;
		image.height = newHeight;
	}
} // ShrinkSizeOfImage()


var _keyUpTimerId;
function _OnKeyUp(evt, ctl, parm, minLength)
{
    if(_keyUpTimerId)
    {
        window.clearTimeout(_keyUpTimerId);
    }
    var strctrl = ctl;
    while(strctrl.indexOf(":")>=0)
    {
		strctrl = strctrl.replace(/:/,"_");
	}
	var element = document.getElementById(strctrl); 
	var s = element.value;
	if(minLength == null)
		minLength = 3;
	s = trim(s);
	ev = evt.keyCode;
	if(s.length >= minLength)
	{
		//fix for FF shft and crtl select bug, stops postback if shft or ctrl key are selected
		if ((ev !== 16) && (ev !== 17))
		{
		var script = "__doPostBack(window.event, '" + ctl + "', 'onkeyup')";
		_keyUpTimerId=window.setTimeout(script, 500);
		}
	}
}

function trim(str)
{
    return str.replace(/^\s*|\s*$/g, ""); 
}

// BEGIN: Delayed thumbnail loading

function LateThumbLoad()
{
	for(var i=0; i < document.images.length; i++)
	{
		var img = document.images[i];
		var attr = img.getAttribute("image");
		if(attr != null && attr.length > 0)
		{
		    //window.status = "Loading image for img[" + i + "]";
			img.setAttribute("image", null);
			img.OnLoadEventHandler = image_load;
			XBrowserAddHandler(img, "load", "OnLoadEventHandler");
			img.src = attr;
			break;
		}
	}
	//if (i == document.images.length) window.status = "Loaded images";
}

function image_load(evt)
{
	window.setTimeout("LateThumbLoad();", 50);
}

function preFetchImage(imageSrc, key)
{
    var image = new Image();
    image.src = imageSrc;
    //alert("preFetchImage():  imageSrc=|" + imageSrc + "|");
    
    if (key) 
    {
        if (!window["PreFetchedImages"]) window["PreFetchedImages"] = new Object();
        window["PreFetchedImages"][key] = image;
    }
}

//window.setTimeout("LateThumbLoad();", 100);

// END: Delayed thumbnail loading


//Pager
var DragObject = {

	obj : null,

	init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
	{
		o.onmousedown	= DragObject.start;

		o.hmode			= bSwapHorzRef ? false : true ;
		o.vmode			= bSwapVertRef ? false : true ;

		o.root = oRoot && oRoot != null ? oRoot : o ;

		if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
		if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
		if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
		if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

		o.minX	= typeof minX != 'undefined' ? minX : null;
		o.minY	= typeof minY != 'undefined' ? minY : null;
		o.maxX	= typeof maxX != 'undefined' ? maxX : null;
		o.maxY	= typeof maxY != 'undefined' ? maxY : null;

		o.xMapper = fXMapper ? fXMapper : null;
		o.yMapper = fYMapper ? fYMapper : null;

		o.root.onDragStart	= new Function();
		o.root.onDragEnd	= new Function();
		o.root.onDrag		= new Function();
	},

	start : function(e)
	{
		var o = DragObject.obj = this;
		e = DragObject.fixE(e);
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		o.root.onDragStart(x, y);

		o.lastMouseX	= e.clientX;
		o.lastMouseY	= e.clientY;

		if (o.hmode) {
			if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
			if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;
		} else {
			if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
			if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
		}

		if (o.vmode) {
			if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
			if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;
		} else {
			if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
			if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
		}

		document.onmousemove	= DragObject.drag;
		document.onmouseup		= DragObject.end;

		return false;
	},

	drag : function(e)
	{
		e = DragObject.fixE(e);
		var o = DragObject.obj;

		var ey	= e.clientY;
		var ex	= e.clientX;
		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		var nx, ny;

		if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
		if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
		if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
		if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

		nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
		ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

		if (o.xMapper)		nx = o.xMapper(y)
		else if (o.yMapper)	ny = o.yMapper(x)

		DragObject.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
		DragObject.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
		DragObject.obj.lastMouseX	= ex;
		DragObject.obj.lastMouseY	= ey;

		DragObject.obj.root.onDrag(nx, ny);
		return false;
	},

	end : function()
	{
		document.onmousemove = null;
		document.onmouseup   = null;
		DragObject.obj.root.onDragEnd(	parseInt(DragObject.obj.root.style[DragObject.obj.hmode ? "left" : "right"]), 
									parseInt(DragObject.obj.root.style[DragObject.obj.vmode ? "top" : "bottom"]));
		DragObject.obj = null;
	},

	fixE : function(e)
	{
		if (typeof e == 'undefined') e = window.event;
		if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
		if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
		return e;
	}
}

//We wrap all the code in an object so that it doesn't interfere with any other code

function scrollerPager() {

  var obj = new Object();
	
  obj.init = function(scrollArea, scroll, pagectrl, totalpagectrl, pages, currentpage, postback,previousbtn,nextbtn) {
    
    var o = this;
	if(document.getElementById(totalpagectrl) == null) return;
    document.getElementById(totalpagectrl).innerHTML = pages;
  
    o.pagectrl = pagectrl;
    o.postback = postback;
    o.currentpage = currentpage;
    
    //collect the variables
    o.contW = 100;
    o.docW = pages * o.contW;
    
    o.scrollAreaW = document.getElementById(scrollArea).offsetWidth;
          
    //calculate width of scrollerPager and resize the scrollerPager div
    //(however, we make sure that it isn't to small for long pages)
    o.scrollW = (o.contW * o.scrollAreaW) / o.docW;
    
    if(o.scrollW < 10) o.scrollW = 20;
    document.getElementById(scroll).style.width = Math.round(o.scrollW) + "px";
    
    //what is the effective scroll distance once the scoller's width has been taken into account
    o.scrollDist = Math.round(o.scrollAreaW-o.scrollW);
    
    //make the scrollerPager div draggable
    DragObject.init(document.getElementById(scroll),null,0,o.scrollDist,0,0, false, true);
    
    //set to current page
    var coef = (((o.docW - o.contW) / o.scrollDist)/o.contW);
    var xpage = (o.currentpage - 1) / coef;
    document.getElementById(scroll).style.left = xpage + "px";    
    document.getElementById(o.pagectrl).innerHTML = o.currentpage;
    
    //add ondrag function
    document.getElementById(scroll).onDrag = function (x,y) {
      var docX = (Math.round((x * (o.docW - o.contW) / o.scrollDist)/o.contW) +1);
      document.getElementById(o.pagectrl).innerHTML = docX;
    }
    
    //add ondragend function
    document.getElementById(scroll).onDragEnd = function (x,y) {
    if(previousbtn!=null)
    {
        DisablePreviousButton(previousbtn);
    }
    if(nextbtn!=null)
    {
        DisableNextButton(nextbtn);
    }
      var docX = -(Math.round(0 - (x * (o.docW - o.contW) / o.scrollDist)/o.contW) -1);
      if(docX != o.currentpage)      
		__doPostBack(null,o.postback, 'pnb:' + docX);
    }
  }
  return obj;
};

//End Pager



// Begin Timers ----------------------------------------------------------------------

var _Timers = new Hash();

function Timer(name, frequency, whatToDo, repeat, onStop)
{
    this._name = name;
    this._frequency = frequency;
    this._whatToDo = whatToDo;
    this._repeat = new Boolean(repeat).valueOf();
    this._timerHandle = 0;
    this._onStop = onStop;
}

Timer.prototype.Start = function()
{
    this.Stop();
    
    //LogReportMonitor("Timer", "Starting timer |" + this._name + "| whatToDo=|" + this._whatToDo + "|");

    if (! this._repeat)
        this._timerHandle = window.setTimeout(this._whatToDo, this._frequency);   // One shot
    else
        this._timerHandle = window.setInterval(this._whatToDo, this._frequency);  // Recurring
}

Timer.prototype.Stop = function()
{
    if (this._timerHandle != 0)
    {
        //LogReportMonitor("Timer", "Stopping timer |" + this._name + "|");
        
        if (! this._repeat)
            window.clearTimeout(this._timerHandle);
        else
            window.clearInterval(this._timerHandle);
            
        this._timerHandle = 0;
    
        if (this._onStop) { StartTimer("", 0, this._onStop, false); }
    }
}

function StartTimer(name, frequency, whatToDo, repeat, onStop)
{
    //LogReportMonitor("Timer", "Entered StartTimer(" + name + ").  _Timers count=|" + _Timers.Count() + "|");
    
    if (name) 
    {
        //LogReportMonitor("Timer", "\t Stopping old " + name + " timer.");
        StopTimer(name);
    }
        
    // TO DO - Maybe alter onStop to include removing the timer from _Timers?
    
    var timer = new Timer(name, frequency, whatToDo, repeat, onStop);
    
    if (name) _Timers.Add(name, timer);

    timer.Start();
}

function StopTimer(name)
{
    //LogReportMonitor("Timer", "Entered StopTimer(" + name + ").  _Timers count=|" + _Timers.Count() + "|");

    if (_Timers.ContainsKey(name))
    {
        var timer = _Timers.Get(name);
        timer.Stop();

        _Timers.Remove(name);
    }
}

// End Timers

function showAlert(str)
{
	alert(unescape(str));
}

// End Timers ----------------------------------------------------------------------



// Begin MemoryLogging ----------------------------------------------------------------------
/*
<a href="#" onclick="AlertMemoryLog('blah'); return false;" style="color:White;background-color:black;">ViewLog</a>
<a href="#" onclick="ClearMemoryLog('blah'); return false;" style="color:White;background-color:black;">ClearLog</a>
*/

var _memoryLogs = new Object();

function MemoryLog(name, msg) 
{
    var log = GetOrCreateMemoryLog(name);
    log.push("" + new Date() + ":" + msg);
}

function AlertMemoryLog(name) 
{
    var log = GetOrCreateMemoryLog(name);
    var msg = "";
    for (var i=0; i<log.length; i++) 
    {
        msg += log[i] + "\n";
    }
    alert(msg);
}

function ClearMemoryLog(name) 
{
    _memoryLogs[name] = null;
}

function GetOrCreateMemoryLog(name)
{
    if (! _memoryLogs[name]) 
    {
        _memoryLogs[name] = new Array();
    }
    return _memoryLogs[name];    
}

// End MemoryLogging ----------------------------------------------------------------------


// Begin ReportMonitor ----------------------------------------------------------------------
// A ReportMonitor displays a box that can be updated at any time to reflect current state, log messages, events, etc.

var _reportMonitors = new Hash();
var _reportMonitorsElement = null;

function ReportMonitorInit()
{
    if (window != top) return top.ReportMonitorInit();
    
    if (! _reportMonitorsElement) 
    {
        var tempElem;
        tempElem = document.createElement("temp");
        tempElem.innerHTML = "<div id=\"_reportMonitors\" style=\"POSITION: absolute; right: 0px; top: 0px; width: auto; height: auto; background-color: transparent; border: 1px solid black; z-index: 4000; padding:3px;\"></div>";
        
        _reportMonitorsElement = document.body.insertBefore(tempElem.firstChild, document.body.firstChild);
    }
}


EnsureReportMonitor = function(name)
{
    if (window != top) return top.EnsureReportMonitor(name);
    
    ReportMonitorInit();

    if (! _reportMonitors.ContainsKey(name))
    {
        var reportMonitor = new ReportMonitor(name);
        _reportMonitorsElement.appendChild(reportMonitor.CreateElement());
        _reportMonitors.Add(name, reportMonitor);
    }
    
    return _reportMonitors.Get(name);
}

UpdateReportMonitor = function(name, content)
{
    if (window != top) return top.UpdateReportMonitor(name, content);
    
    ReportMonitorInit();
    var reportMonitor = EnsureReportMonitor(name);
    reportMonitor.UpdateContent(content);
}

UpdateReportMonitorHtml = function(name, html)
{
    if (window != top) return top.UpdateReportMonitorHtml(name, html);
    
    ReportMonitorInit();
    var reportMonitor = EnsureReportMonitor(name);
    reportMonitor.UpdateHtml(html);
}

LogReportMonitor = function(name, content)
{
    AppendReportMonitor(name + " Log", GetCurrentDateTimeString() + " " + content);
}

AppendReportMonitor = function(name, content)
{
    if (window != top) { top.AppendReportMonitor(name, content); return; }
    
    ReportMonitorInit();
    var reportMonitor = EnsureReportMonitor(name);
    reportMonitor.AppendContent(content);
}

UpdateReportMonitorStyle = function(name, style, value)
{
    if (window != top) return top.UpdateReportMonitorStyle(name, style, value);

    ReportMonitorInit();
    var reportMonitor = EnsureReportMonitor(name);
    reportMonitor.UpdateStyle(style, value);
}

ClearReportMonitor = function(name)
{
    if (window != top) return top.ClearReportMonitor(name);
    
    UpdateReportMonitor(name, "");
}

RemoveReportMonitor = function(name)
{
    if (window != top) return top.RemoveReportMonitor(name);
    
    ReportMonitorInit();

    if (_reportMonitors.ContainsKey(name))
    {
        var reportMonitor = _reportMonitors[name];
        reportMonitor.GetElement().parentNode.removeChild(reportMonitor.GetElement());
        
        _reportMonitors.Remove(name);
    }
}

ReportMonitorToggleExpanded = function(name)
{
    if (window != top) return top.ReportMonitorToggleExpanded(name);
    
    ReportMonitorInit();

    if (_reportMonitors.ContainsKey(name))
    {
        var reportMonitor = _reportMonitors[name];
        reportMonitor.ToggleExpanded();
    }
    else
        alert("No such ReportMonitor '" + name + "'");
    
}

GetReportMonitor = function(name)
{
    return _reportMonitors[name];
}


function ReportMonitor(name)
{
    this.name = name;
    this.expanded = true;
    this.opaque = true;
}
ReportMonitor.prototype.GetElement = function() { return this.element; }
ReportMonitor.prototype.GetId = function() { return "_reportMonitor_" + this.name; }
ReportMonitor.prototype.GetHeaderId = function() { return "_reportMonitor_" + this.name + "Header"; }
ReportMonitor.prototype.GetContentId = function() { return "_reportMonitor_" + this.name + "Content"; }
ReportMonitor.prototype.GetContentElement = function() 
{ 
    if (! this.contentElement) 
    {
        this.contentElement = document.getElementById(this.GetContentId());
        if (! this.contentElement)
            alert("Can't find ReportMonitor contentElement w/ id=|" + this.GetContentId() + "|");
    }
    return this.contentElement;    
}

ReportMonitor.prototype.GetToggleId = function() { return "_reportMonitor_" + this.name + "Toggle"; }
ReportMonitor.prototype.GetToggleElement = function() 
{ 
    if (! this.toggleElement) 
    {
        this.toggleElement = document.getElementById(this.GetToggleId());
        if (! this.toggleElement)
            alert("Can't find ReportMonitor toggleElement w/ id=|" + this.GetToggleId() + "|");
    }
    return this.toggleElement;    
}

ReportMonitor.prototype.CreateElement = function()
{
    if (! this.element)
    {
        var id = this.GetId();
        var tempElem;
        tempElem = document.createElement("temp");
        tempElem.innerHTML = "<table id=\"" + id + "\" style=\"POSITION: relative; display:block; top: 0px; max-height: 200px; overflow:auto; width: auto; border: 1px solid black; padding:3px; font-size: 11px; font-family: tahoma, arial, Helvetica, sans-serif; background-color:white; \"" +
                             //" onclick=\"RemoveReportMonitor('" + this.name + "');\" " +
                             ">" +
                                 "<tr>" +
                                 "<td align=\"center\"><div id=\"" + this.GetHeaderId() + "\" style=\"font-weight: bold; border-bottom: 1px solid black;\">" + this.name + "</div></td>" +
                                 "<td align=\"right\">" +
                                    "<span onclick=\"GetReportMonitor('"+this.name+"').ToggleOpacity();\" style=\"border: 1px solid black; cursor: pointer; padding-left:2px;\"> O </span>&nbsp;" +
                                    "<span onclick=\"ClearReportMonitor('" + this.name + "')\" style=\"border: 1px solid black; cursor: pointer; \"> C </span>&nbsp;" +
                                    "<span id=\"" + this.GetToggleId() + "\" onclick=\"ReportMonitorToggleExpanded('" + this.name + "');\" style=\"border: 1px solid black; cursor: pointer;\">" + (this.expanded?" M ":" E ") + "</span>&nbsp;" +
                                 "</td>" +
                                 "</tr>" +
                                 "<tr><td colspan=\"2\"><div id=\"" + this.GetContentId() + "\" style=\"height:auto; width: auto;\"></div></td></tr>" +
                             "</table>";
        this.element = tempElem.firstChild;
        
        SetElementOpacity(this.element, 50);
    }
    
    return this.element;
}

ReportMonitor.prototype.UpdateStyle = function(style, value)
{
    var stmt = "this.element.style." + style + " = \"" + value + "\"";
    eval(stmt);
} 

ReportMonitor.prototype.UpdateHtml = function(html)
{
    var contentElement = this.GetContentElement();
    contentElement.innerHTML = html;
}

ReportMonitor.prototype.UpdateContent = function(content)
{
    var contentElement = this.GetContentElement();
    contentElement.innerHTML = this.PrepareContent(content);
}

ReportMonitor.prototype.AppendContent = function(content)
{
    var contentElement = this.GetContentElement();
    var origContentHTML = contentElement.innerHTML;
    contentElement.innerHTML = this.PrepareContent(content) + "<br>" + origContentHTML;
}


ReportMonitor.prototype.PrepareContent = function(content)
{
    return content.replace(/\t/gm,"&nbsp;&nbsp;&nbsp;").replace(/ /gm,"&nbsp;").replace(/</gm,"&lt;").replace(/\n/gm,"<br>");
}

ReportMonitor.prototype.ToggleExpanded = function()
{
    //alert("Entered ToggleExpanded() for ReportMonitor " + this.name + " " + this.expanded + " to " + (! this.expanded));
 
    this.expanded = (! this.expanded);
    
    this.GetToggleElement().innerHTML = (this.expanded?" M ":" E ");
    
    if (! this.expanded)
        this.GetContentElement().style.display = "none";
    else
        this.GetContentElement().style.display = "";
}

ReportMonitor.prototype.ToggleOpacity = function()
{
    //alert("Entered ToggleOpacity() for ReportMonitor " + this.name + " " + this.opaque + " to " + (! this.opaque));
    
    this.opaque = (! this.opaque);
    
    if (this.opaque)
        SetElementOpacity(document.getElementById(this.GetId()), 50);
    else
        SetElementOpacity(document.getElementById(this.GetId()), 100);
}



// End ReportMonitor ----------------------------------------------------------------------

// Begin Hash ----------------------------------------------------

function Hash() 
{
    this.Keys = new Array();
}


Hash.prototype.Dispose = function()
{
    this.Keys = null;
}

Hash.prototype.Count = function()
{
    return this.Keys.length;
}

Hash.prototype.KeysString = function() 
{
    var s = "";
    for (var i=0; i<this.Keys.length; i++) 
    {
        if (i > 0) s += ",";
        s += this.Keys[i];
    }
    return s;
}
Hash.prototype.ContainsKey = function(key)
{
    for (var i=0; i<this.Keys.length; i++) 
    {
        var akey = this.Keys[i];
        //alert("Hash: Comparing akey=|" + akey + "|  to key=|" + key + "|");
        if (akey == key) return true;
    }
    return false;
}
Hash.prototype.Add = function(key, value)
{
    if (! this.ContainsKey(key))
    {
        this.Keys.push(key);
        //alert("Hash: Added key=|" + key + "|");
    }
    this[key] = value;
}
Hash.prototype.Get = function(key)
{
    return this[key];
}
Hash.prototype.Remove = function(key)
{
    for (var i=0; i<this.Keys.length; i++)
    {
        if (this.Keys[i] == key) 
        {
            this.Keys.splice(i, 1);
            break;
        }
    }
    this[key] = null;
}

Hash.prototype.Clone = function()
{
    var hash = new Hash();
    for (var i=0; i<this.Keys.length; i++) 
    {
        hash.Add(this.Keys[i], this.Get(this.Keys[i]));
    }
    return hash;
}

function CreateHashFromKeyValues(keyValues) 
{
    var hash = new Hash();
    
    for (var i=0; i<keyValues.length; i++)
    {
        var keyValue = keyValues[i];
        var key = keyValue[0];
        var value = keyValue[1];
        hash.Add(key, value);
    }
    
    return hash;
}
// End Hash ----------------------------------------------------


function CloneObject(obj)
{
    var newObj = new Object();
    
    for (var prop in obj)
    {
        try { newObj[prop] = obj[prop]; }
        catch (ex) 
        { 
            //LogReportMonitor("Clone", "error setting " + prop + ".  Exception=|" + ex + "|"); 
        }
    }
    
    return newObj;
}


var DelayedPostBackCounter = 0;
var _delayedPostbackEvents = new Array();

function CloneEvent(evt)
{
    var newEvent = null;
    
    /*
    LogReportMonitor("Events", "CloneEvent():  evt=" + GetEventDataMsg(evt) + "\n" +
                               "eventType=" + evt.type + "\n" +
                               "");
    */
    if (document.createEvent)
    {
        var moduleName = EventTypeToEventModule(evt.type);
        newEvent = document.createEvent(moduleName);
        switch (moduleName)
        {
            case "MouseEvents":
                newEvent.initMouseEvent(evt.type, evt.bubbles, evt.cancelable,
                                        evt.view, evt.detail,
                                        evt.screenX, evt.screenY, evt.clientX, evt.clientY,
                                        evt.ctrlKey, evt.altKey, evt.shiftKey, evt.metaKey,
                                        evt.button, evt.relatedTarget);
                break;
            case "HTMLEvents":
            case "UIEvents":
            case "MutationEvents":
                throw "Module not supported (yet): " + moduleName;
            default:
                throw "Unknown module: " + moduleName;
        }
    }
    else if (document.createEventObject)
    {
        newEvent = document.createEventObject();
    }
    
    for (var prop in evt)
    {
        try 
        { 
            newEvent[prop] = evt[prop];
            //eval("newEvent." + prop + " = evt." + prop); 
        }
        catch (ex) 
        { 
            //LogReportMonitor("EventsErrors", "error setting " + prop + ".  Exception=|" + ex + "|"); 
        }
    }
    
    var srcId = null;
    if(evt.currentTarget)
        srcId = evt.currentTarget.id;
    else if (evt.srcElement)
        srcId = evt.srcElement.id;
    
    newEvent.srcElementId = srcId;
    return newEvent;
}

function SetupDelayedPostBack(event, postbackCall, delay)
{
   //alert("Entered SetupDelayedPostBack()");
     var myCounter = ++DelayedPostBackCounter;
    if(event.currentTarget)
       _delayedPostbackEvents[myCounter] = event;
    else
       _delayedPostbackEvents[myCounter] = CloneEvent(event);
    //window["DelayedPostBackEvent_" + myCounter] = event;       // Save the event object so that the timer can get it.
    window.setTimeout("DelayedPostBack(" + myCounter + ", \"" + postbackCall + "\")", delay);
}

function DelayedPostBack(counter, postbackCall)
{
    //alert("Entered DelayedPostBack(): postbackCall=|" + postbackCall + "|");
    //var eventParm = "window['DelayedPostBackEvent_" + counter + "']";
    var eventParm = "_delayedPostbackEvents[" + counter + "]";
    var str = postbackCall.replace(/event/, eventParm);
    if (window.execScript)
        window.execScript(str);
    else
        window.eval(str);
}
function DisablePreviousButton(controlId)
{
    var node=document.getElementById(controlId);  
                   
            if(!xpbutton_active(controlId))
            {
                node.disabled=true;
                node.className='xpbuttonDisabled';               
                 return false;
             }
}
function DisableNextButton(controlId)
{
    var node=document.getElementById(controlId);  
                   
            if(!xpbutton_active(controlId))
            {
                node.disabled=true;
                node.className='xpbuttonDisabled';               
                 return false;
             }
}

function SaveLocalTimeOffset()
{
    var hiddenField = document.getElementsByName("__TIMEDIFF");
    if(hiddenField.length > 0)
    {
        var rightNow = new Date();
        hiddenField[0].value =  -1 * rightNow.getTimezoneOffset() ;
    }
}

function SetFocusOnBodyLoad(delayed)
{
    if(delayed)
    {
        window.setTimeout("SetFocusOnBodyLoad(false);", 100);
        return;
    }
    var frameForm = document.forms[0];
    
    var found = false;
    //let's find input tag with "defaultfocus" attribute set to true
    for (var frameElementIndex = 0; frameElementIndex < frameForm.elements.length; frameElementIndex++) 
    {
        var field = frameForm.elements[frameElementIndex];
        if (field.name) 
        {
            var fType = field.type.toLowerCase();
            switch(fType)
            {
                case "text":
                case "textarea":
                case "password":
                case "file":
                try
                {
                    if(field.getAttribute("defaultfocus") == true)
                    {
                        field.focus();
                        found = true;
                    }
                }
                catch(focusError)
                {
                    //if there was an error continue to the next field
                }
                break;
            }
        } 
        if(found) break;
    }

    //if input field with "defaultfocus" attribute not found or it is invisible then set focus to the first
    //visible input field
    if(!found)
    {    
        for (var frameElementIndex = 0; frameElementIndex < frameForm.elements.length; frameElementIndex++) 
        {
            var field = frameForm.elements[frameElementIndex];
            if (field.name) 
            {
                var fType = field.type.toLowerCase();
                switch(fType)
                {
                    case "text":
                    case "textarea":
                    case "password":
                    case "file":
                    try
                    {
                        field.focus();
                        found = true;
                    }
                    catch(focusError)
                    {
                        //if there was an error continue to the next field
                    }
                    break;
                }
            } 
            if(found) break;
        }
    }
}


// String enhancements

String.prototype.StartsWith = function(prefix)
{
    var length = prefix.length;
    
    var value = (this.substring(0, length) == prefix)
    
    //alert("StartsWith():  s=|" + this + "|  prefix=|" + prefix + "|  value=|" + value + "|");
    
    return value;
}




