function gEBI(i){ 
	return document.getElementById(i);
	} /* gEBI(i) */

function dataObject() {
	this.Tables = {};
	this.AJAX = '';
	this.Encoding = "application/x-www-form-urlencoded; charset=UTF-8";
	this.AuthToken = "NoAuth";
	this.ShowWorkingId = "";
	this.DBGOut = "" ;
	this.User = {'Menu0825Id':'','Login':'','IP':'','Session':''} ;
	
	if (window.XMLHttpRequest)  // Mozilla and Safari
		this.AJAX = new XMLHttpRequest();
	else if (window.ActiveXObject) // IE
		this.AJAX = new ActiveXObject("Microsoft.XMLHTTP");
	
	this.getURL = utilGetURL;
	this.newTable = utilNewTable;
	this.fillSelect = utilFillSelect;
	this.fillSelectByElement = utilFillSelectByElement;
	this.getTableHTML = utilGetTableHTML;
	this.ih = utilInnerHTMLStub;
	this.debug = utilDebug;
	this.setAllId = utilSetAllId;
	this.dumpStateInfo = dtoDumpStateInfo;
	
	
	this.setEncoding = utilSetEncoding;
	
	this.cleanString = cleanString;

	var loAuthToken = gEBI("AuthToken") ;
	if (loAuthToken) {
		this.AuthToken = loAuthToken.value ;
		try{
			var lcObj = this.getURL("/Common/Ajax/Menu0825UserInfo.asp")  ;
			this.User = eval("(" + lcObj + ")") ;
			}
		catch(e) {			
			}
		}
	
	} /* dataObject() */

function utilSetEncoding( newEncoding )
{
	this.Encoding = newEncoding;
}
/* utility functions for the object - coded this way, the function is defined in the environment once and the object references the existing function definition (lowers overhead compared with multiple declarations of inline functions) */	
function utilGetURL( tcURL, txObj ) {
	var rv = "";
	var loAJAX = this.AJAX;

	loAJAX.open("post", tcURL, false);
	loAJAX.setRequestHeader("Content-Type", this.Encoding );
	
	if(txObj){
		if (typeof txObj == "string") {
			var lcObjStr = txObj ;
			}
		else {
			var lcObjStr = txObj.toJSONString();
			}
		var encURIC = (window.encodeURIComponent) ?
						encodeURIComponent( lcObjStr )  :
						PBPencodeURI( lcObjStr ) ;

		loAJAX.send("AuthToken=" + this.AuthToken +"&Object=" + encURIC );
		
		}
	else {
		loAJAX.send("AuthToken=" + this.AuthToken );
		}
		
	if(loAJAX.readyState==4) {
		switch( loAJAX.status ){
			case 200 : /* ok */
				rv = loAJAX.responseText; //.replace(/\n/g,"\n") ;
				break;
			case 404 : /* page not found */
				rv = "{'Rows':[]," +
						"'Errors':[{" +
							"'Name':'AJAX'," +
							"'Number':404," +
							"'Description':'Page not found'," +
							"'Message':'AJAX Page not found (404)'" +
							"}]" +
						"}" ;
				break;
			case 500 : /* internal server error */
				rv = "{'Rows':[]," +
						"'Errors':[{" +
							"'Name':'AJAX'," +
							"'Number':500," +
							"'Description':'Server Error'," +
							"'Message':'AJAX Server Error (500)'" +
							"}]" +
						"}" ;
				break;
			default :
				rv = "{'Rows':[]," +
						"'Errors':[{" +
							"'Name':'AJAX'," +
							"'Number':" + loAJAX.status + "," +
							"'Description':'General Error'," +
							"'Message':'AJAX Server Error (" + loAJAX.status + ")'" +
							"}]" +
						"}" ;
				break;
			} /* switch(loAJAX.status) */
		} /* if(loAJAX.readyState==4) */
	else {
		rv = "{'Rows':[]," +
				"'Errors':[{" +
					"'Name':'AJAX'," +
					"'Number':" + loAJAX.readyState + "," +
					"'Description':'Control not ready'," +
					"'Message':'AJAX Control not ready (" + loAJAX.readyState + ")'" +
					"}]" +
				"}" ;
		
		} /* if(loAJAX.readyState==4) */
	
	return rv ;
	} ; /* getURL(..) */
function utilNewTable (tcTableName,tcSourceURL,tcObjToServer) {
		var llOK = true;
		
		if (this.ShowWorkingId) {
			var loSWI = gEBI(this.ShowWorkingId) ;
			if (loSWI) { loSWI.style.display = 'block'; }
			} /* if (this.ShowWorkingId) */
		
		/* get a json string via ajax... */
		var lcJSON = this.getURL( tcSourceURL, tcObjToServer );
		try{
			this.Tables[ tcTableName ] = eval("(" + lcJSON + ")");
			}
		catch(e) {
			llOK = false;
			this.debug( "Unable to parse object from WebService" );
			}
			
		/* check the errors collection */
		if( llOK ) {
			llOK = (this.Tables[ tcTableName ].Errors.length <= 0);
			} /* (..Errors.length > 0) */
		
		if( llOK ) {
			/* there are no errors */
			/* initialize EOF/BOF so if there are no rows, the EOF/BOF is set similarly to ADO */
			this.Tables[ tcTableName ].BOF = true; /* initialize BOF */
			this.Tables[ tcTableName ].EOF = true; /* initialize EOF */
			
			if (this.Tables[ tcTableName ].Rows.length > 0) {
				this.Tables[ tcTableName ].CurrentRowNdx = 0; /* set current row index(ndx)  to the first row */
				this.Tables[ tcTableName ].CurrentRow = this.Tables[ tcTableName ].Rows[0]; /* set CurrentRow object to first row */
				this.Tables[ tcTableName ].BOF = false; /* reset BOF */
				this.Tables[ tcTableName ].EOF = false; /* reset EOF */
				
				this.Tables[ tcTableName ].get = tableGetField; 
				this.Tables[ tcTableName ].set = tableSetField;
				
				this.Tables[ tcTableName ].addRow = tableAddRow;
				this.Tables[ tcTableName ].removeRow = tableRemoveRow;
				
				this.Tables[ tcTableName ].revert = tableRevertData;
				
				this.Tables[ tcTableName ].move = tableMove;
				
				/* Methods to shortcut .Move behaviors similiar to ADO */
				this.Tables[ tcTableName ].moveNext = function(){ this.move(1,0) };
				this.Tables[ tcTableName ].movePrevious = function(){ this.move(-1,0)} ;
				this.Tables[ tcTableName ].moveFirst = function(){ this.move(0,1)};
				this.Tables[ tcTableName ].moveLast = function(){ this.move(0,2)};
				} /* if(this.Tables[ tcTableName ].Rows.length > 0) */
			} /* if(llOK) */

		if (this.ShowWorkingId) { 
			setTimeout( "var loSWI=gEBI('" + this.ShowWorkingId + "');if(loSWI){loSWI.style.display = '';}",1);
			} /* if (this.ShowWorkingId) */
	
		return llOK;
		} ; /* newTable(..) */
function utilFillSelectByElement (toSelect, tcTableName, tcOptionPromptField, tcOptionValueField, tcSelectedValue) {
	var loS = toSelect;
	var loT = this.Tables[tcTableName];
	if(loT && loT.Rows.length > 0) {
		var lnOVPI = loT.Fields[ tcOptionPromptField ].Index ; /* Option Prompt Field Index */
		var lnOVFI = loT.Fields[ tcOptionValueField ].Index ; /* Option Value Field Index */
		
		loS.options.length = 0 ; /* clear the existing options list */
		for(var lnR = 0; lnR < loT.Rows.length; lnR++) { /* iterate the table Rows */
			var lcPrompt = loT.Rows[lnR][ lnOVPI ] ; /* the option text from this row of data */
			var lcValue = loT.Rows[lnR][ lnOVFI ] ; /* the option value from this row of data */
			
			var n = loS.options.length ; /* get new option index number */
			loS.options[ n ] = new Option(lcPrompt,lcValue) ; /* add the new option */
			loS.options[ n ].selected = (lcValue == tcSelectedValue) ; /* set the selected flag if the value matches what was passed */
			} /* for( lnR ) */
		} /* if(loT) */
	}
function utilFillSelect (tcSelectId, tcTableName, tcOptionPromptField, tcOptionValueField, tcSelectedValue) {
	var loS = gEBI( tcSelectId );
	if(loS) {
		this.fillSelectByElement( loS, tcTableName, tcOptionPromptField, tcOptionValueField, tcSelectedValue);
		}
	}
function utilGetTableHTML(tcTableName) {
	/* primarily a debugging tool since it expects innerHTML to actually insert this HTML into the DOM */
	/* if there were ever a non-debugging use for this function, it should be implemented using proper DOM methods */
	var lcHTML = "<table>";
	var loT = this.Tables[tcTableName];
	if (loT) {
		lcHTML += "<tr>";
		for(var lnF = 0; lnF < loT.Fields.Count; lnF++) {
			lcHTML += "<th>" + loT.Fields.Index[lnF] + "</th>";
			}
		lcHTML += "</tr>";
		
		for( var lnR = 0; lnR < loT.Rows.length; lnR++) {
			lcHTML += "<tr>";
			for(var lnF = 0; lnF < loT.Fields.Count; lnF++) {
				lcHTML += "<td>" + loT.Rows[lnR][lnF] + "</td>" ;
				}
			lcHTML += "</tr>";
			} /* for(lnR) */
		} /* if(loT) */
	lcHTML += "</table>";
	
	return lcHTML;
	} /* utilGetTableHTML */
function utilInnerHTMLStub(txObjId, tcStr) { // encapsulate innerHTML use
// note:  this function/method returns the innerHTML, so it can be called with just an object reference/id (read) or include the second arguement to set (write)

	var loObj = txObjId ; // default = object was passed
	if( typeof (txObjId) == "string" ) { // resolve string id to an object
		loObj = document.getElementById(txObjId);
		}
	if(tcStr && tcStr!="undefined" ) {
		loObj.innerHTML = tcStr;
		}
	return (loObj.innerHTML);
	}
function utilSetAllId( k, v ) {
	var lnI = 0;
	var lcKey = k;
	var n = gEBI( lcKey )
	while (n) {
		switch( n.nodeName.toLowerCase() ) {
			case 'input' :
				n.value = v;
				break ;
			case 'span' :
			case 'div' :
			case 'textarea' :
			case 'label' :
				try{
					this.ih( n, v );
					}
				catch(e){
					n.innerHTML = v;
					}
				break;
			default :
				break ;
			}
			
		lnI++;	
		lcKey = k + lnI.toString() ;
		n = gEBI( lcKey );
		}
	}		
	
function utilDebug(tcStr, tcAdd, tcDbgId) {
	var lcDbgId = (tcDbgId) ? tcDbgId : this.DBGOut ; // if not passed, set to dto default
	if (lcDbgId != "") {
		switch( String(tcAdd) ) {
			case "1" :
			case "before" :
				this.ih( lcDbgId, tcStr + this.ih( lcDbgId ) + "<br />") ;
				break;
			case "2" :
			case "after" :
				this.ih( lcDbgId, this.ih( lcDbgId ) + tcStr + "<br />") ;
				break;
			case "0" :
			case "replace" :
			default :
				this.ih( lcDbgId, tcStr );
				break;
			}
		}
	else {
		alert( tcStr );
		}
	}	
/* functions assigned to each new table - again, this saves resources by calling existing function definitions rather than multiple inline redundancy */
function tableMove(tnRows, tnRelativeTo) { /* set up the method for moving the CurrentRow pointer */
	var newRowIndex = this.CurrentRowNdx ; /* set a local variable rather than using raw object references */
	switch(tnRelativeTo) {
		case 1 : /* FirstRecord */
			newRowIndex = tnRows ;
			break;
		case 2 : /* LastRecord */
			newRowIndex = (this.Rows.length - 1) + tnRows ;
			break;
		default : /* Current Record */
			newRowIndex += tnRows ;
			break;
		} /* switch(tnRelativeTo) */
	this.EOF = ( newRowIndex >= this.Rows.length );
	this.BOF = ( newRowIndex < 0 ) ;
	/* set the current row to the new value */
	this.CurrentRowNdx = newRowIndex ;
	this.CurrentRow = this.Rows[ newRowIndex ];
	} /* tableMove */
function tableGetField ( tcFieldName, tcGetWhat ) {
	var rv ;
	var loF = this.Fields[ tcFieldName ];
	if( !tcGetWhat || tcGetWhat=="undefined" || tcGetWhat == '') { tcGetWhat = 'Value' };  /* cast unspecified or empty tcGetWhat to 'Value' */
	if (loF) { /* does the field requested exist */
		var lnFI = loF.Index ; // local variable reduces calls to object property
		switch( tcGetWhat.toLowerCase() ){
			case 'value' :
				rv = this.CurrentRow[ lnFI ];
				break ;
			case 'originalvalue' :
				/* if there is an originalvalues array (because a setter operation had reason to create one) and there is a value set for the current field */
				if( this.CurrentRow.isNew || (this.CurrentRow[ "OriginalValues" ] && this.CurrentRow[ "OriginalValues" ][ lnFI ]) ) {
					rv = this.CurrentRow[ "OriginalValues" ][ lnFI ];
					}	
				else { // there was no change to the field being requested, so the current value IS the originalvalue
					rv = this.CurrentRow[ lnFI ];
					}
				break ;
			case 'ischanged' : // this row has a ChangedField collection (if it doesn't, then the data obviously isn't changed) AND the current changed status
				rv = ( this.CurrentRow["ChangedField"] && this.CurrentRow["ChangedField"][ lnFI ] ) ; 
				break ;
			default :
				rv = loF[ tcGetWhat ];
				break ;
			} /* switch(tcGetWhat) */
		} /* if(loF) */
	return rv ;
	} /* tableFieldGet */
function tableSetField( tcFieldName, txNewValue ) {
	var loF = this.Fields[ tcFieldName ];
	if (loF) { /* does the requested field  exist */
		var lnFI = loF.Index ; // local variable reduces calls to object property

		this.CurrentRow[ "isChanged" ] = true; // mark the isChanged status for this row 
		if ( ! this.CurrentRow["ChangedField"] ) { // make sure the ChangedField array exists for this row
			this.CurrentRow["ChangedField"] = new Array();
			}
		this.CurrentRow[ "ChangedField" ][lnFI] = true; // set the changed status for this field
		
		if( !this.CurrentRow["OriginalValues"] ) { // make sure the Originalvalues array exists for this row
			this.CurrentRow["OriginalValues"] = new Array();
			}
		if( !this.CurrentRow["OriginalValues"][ lnFI ] && !this.CurrentRow["isNew"] ) { // if there is no value in the OriginalValues array and the CurrentRow is not new (new rows would have literal undefined as original values which should not be overwritten with first value when second value is applied)
			this.CurrentRow["OriginalValues"][ lnFI ] = this.CurrentRow[ lnFI ] ; 
			}

		this.CurrentRow[ lnFI ] = txNewValue; // set the value specified
		} /* if(loF) */
	} /* tableSetField */
function tableAddRow() { /* add a new row to the end of this table */
	var lnNewRow = this.Rows.length;
	this.Rows[ lnNewRow ] = new Array();
	this.moveLast();
	this.CurrentRow[ "isNew" ] = true; /* it's new, so flag it that way in case there is a revert row */
	this.CurrentRow[ "isChanged" ] = true; /* of course it is changed, it's new - this is just convenient for routines than iterate a table looking for isChanged */
	// let the Set function deal with field-level change status
	} /* tableAddRow() */
function tableRemoveRow() { /* remove the current row from this table */
	if (! (this.EOF || this.BOF) ) { /* the current row valid? */
		this.Rows.splice( this.CurrentRowNdx, 1); /* remove the current row */
		this.move(0); /* move the record pointer 0 rows relative to the current row - this automatically solves the issue of a deleted array index, the CurrentRowNdx, and EOF */
		} /* if (! (this.EOF || this.BOF) ) */
	} /* tableRemoveRow()  */
function tableRevertData(tcFieldName) {
	if(tcFieldName){
		this.set(tcFieldName, this.get(tcFieldName,'OriginalValue') );
		this.CurrentRow["ChangedField"][ this.get(tcFieldName,'Index') ] = false;
		}
	else { // no fieldname supplied, revert the entire current row
		for( var lnFI in this.CurrentRow["ChangedField"] ) {
			var lcFN = this.Fields.Index[lnFI];
			this.set( lcFN, this.get( lcFN, 'OriginalValue') );
			this.CurrentRow["ChangedField"][ this.get( lcFN,'Index' ) ] = false;
			}
		this.CurrentRow["isChanged"] = this.CurrentRow["isNew"] ;  // if it's not new, set ischanged to false, if it is new, leave the isChanged set to true so iterating the table for isChanged will still catch the new row
		}
	} /* tableRevertData */
	
/* swiped functions to deal with html/url encoding */
function URLEncode( tcStr ) {
// ====================================================================
//       URLEncode and URLDecode functions
//
// Copyright Albion Research Ltd. 2002
// http://www.albionresearch.com/
//
// You may copy these functions providing that 
// (a) you leave this copyright notice intact, and 
// (b) if you use these functions on a publicly accessible
//     web site you include a credit somewhere on the web site 
//     with a link back to http://www.albionresarch.com/
//
// If you find or fix any bugs, please let us know at albionresearch.com
//
// SpecialThanks to Neelesh Thakur for being the first to
// report a bug in URLDecode() - now fixed 2003-02-19.
// ====================================================================
/*
Modified to pass in a string and pass out a string rather than the hardcoded form references
*/
	// The Javascript escape and unescape functions do not correspond
	// with what browsers actually do...
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var plaintext = tcStr;
	var encoded = "";
	for (var i = 0; i < plaintext.length; i++ ) {
		var ch = plaintext.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
			    alert( "Unicode Character '" 
                        + ch 
                        + "' cannot be encoded using standard URL encoding.\n" +
				          "(URL encoding only supports 8-bit characters.)\n" +
						  "A space (+) will be substituted." );
				encoded += "+";
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	} // for

	return encoded;
};
function URLDecode( tcStr ) {
   // Replace + with ' '
   // Replace %xx with equivalent character
   // Put [ERROR] in output if %xx is invalid.
   var HEXCHARS = "0123456789ABCDEFabcdef"; 
   var encoded = tcStr;
   var plaintext = "";
   var i = 0;
   while (i < encoded.length) {
       var ch = encoded.charAt(i);
	   if (ch == "+") {
	       plaintext += " ";
		   i++;
	   } else if (ch == "%") {
			if (i < (encoded.length-2) 
					&& HEXCHARS.indexOf(encoded.charAt(i+1)) != -1 
					&& HEXCHARS.indexOf(encoded.charAt(i+2)) != -1 ) {
				plaintext += unescape( encoded.substr(i,3) );
				i += 3;
			} else {
				alert( 'Bad escape combination near ...' + encoded.substr(i) );
				plaintext += "%[ERROR]";
				i++;
			}
		} else {
		   plaintext += ch;
		   i++;
		}
	} // while
   return plaintext;
};

// FROM: http://www.bindows.net/webboard/?action=display&id=4238&group=data/general (changed to PBPencodeURI)
PBPencodeURI = function (str) { // Correctly handle URI encoding, preventing bug of browsers to convert special chars (ie: ü as Ã¼)
    var newStr = ""; var dec;
    var itens = "0123456789ABCDEF";
    for (var i = 0; i < str.length; i++) {
        dec = (str.charAt(i)).charCodeAt(0);
        // 0-9 (48-57), A-Z (65-90), a-z (97-122)
        if (!(dec >= 48 && dec <= 57) && !(dec >= 65 && dec <= 90) && !(dec >= 97 && dec <= 122))
            newStr += "%" + String(itens.charAt((dec - (dec % 16)) / 16) + itens.charAt(dec % 16));
        else newStr += str.charAt(i);
    }
    return newStr;
}
PBPdecodeURI = function (str) { // Handle URI decoding
    var newStr = ""; var hex;
    var itens = "0123456789ABCDEF";

    for (var i = 0; i < str.length; i++) {
        if (str.charAt(i) == "%") {
            hex = String(str.charAt(i + 1) + str.charAt(i + 2));
            newStr += String.fromCharCode(parseInt(hex, 16));
            i = i + 2;
        } else {
            newStr += str.charAt(i);

            if (str.charAt(i) == "%" && str.charAt(i + 1) == "%") i++;
        }
    }

    return newStr;
}

// FROM: http://www.samspublishing.com/articles/article.asp?p=30111&seqNum=3&rl=1
function Array_splice(index, delTotal) { // because some browsers appear to be broken despite having the same configuration (build number, advanced settings, etc) as a working installation
  var temp = new Array()
  var response = new Array()
  var A_s = 0
  for (A_s = 0; A_s < index; A_s++) {
   temp[temp.length] = this[A_s]
   }
  for (A_s = 2; A_s < arguments.length; A_s++) {
   temp[temp.length] = arguments[A_s]
   }
  for (A_s = index + delTotal; A_s < this.length; A_s++) {
   temp[temp.length] = this[A_s]
   }
  for (A_s = 0; A_s < delTotal; A_s++) {
   response[A_s] = this[index + A_s]
   }
  this.length = 0
  for (A_s = 0; A_s < temp.length; A_s++) {
   this[this.length] = temp[A_s]
   }
  return response
  }
if (typeof Array.prototype.splice == "undefined") {
  Array.prototype.splice = Array_splice ;
  }

/* upgrade to object and array to create JSON string
FROM:  http://www.json.org/json.js   2006-04-28
object.toJSONString()	This method produces a JSON text from an object.  The object must not contain any cyclical references.
array.toJSONString()	This method produces a JSON text from an array.  The array must not contain any cyclical references.
*/
(function () {
    var m = {
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        s = {
            array: function (x) {
                var a = ['['], b, f, i, l = x.length, v;
                for (i = 0; i < l; i += 1) {
                    v = x[i];
                    f = s[typeof v];
                    if (f) {
                        v = f(v);
                        if (typeof v == 'string') {
                            if (b) {
                                a[a.length] = ',';
                            }
                            a[a.length] = v;
                            b = true;
                        }
                    }
                }
                a[a.length] = ']';
                return a.join('');
            },
            'boolean': function (x) {
                return String(x);
            },
            'null': function (x) {
                return "null";
            },
            number: function (x) {
                return isFinite(x) ? String(x) : 'null';
            },
            object: function (x) {
                if (x) {
                    if (x instanceof Array) {
                        return s.array(x);
                    }
                    var a = ['{'], b, f, i, v;
                    for (i in x) {
						try{						
							v = x[i];
							f = s[typeof v];
							if (f) {
								v = f(v);
								if (typeof v == 'string') {
									if (b) {
										a[a.length] = ',';
										}
									a.push(s.string(i), ':', v);
									b = true;
									}
								}
							}
						catch(e){ 
							a.push(',', s.string(i), ':', s.string(e) );
						}	
					}
                    a[a.length] = '}';
                    return a.join('');
                }
                return 'null';
            },
            string: function (x) {
                if (/["\\\x00-\x1f]/.test(x)) {
                    x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                        var c = m[b];
                        if (c) {
							return c;
                        }
                        c = b.charCodeAt();
                        return '\\u00' +
                            Math.floor(c / 16).toString(16) +
                            (c % 16).toString(16);
                    });
                }
                return '"' + x + '"';
            }
        };

    Object.prototype.toJSONString = function () {
        return s.object(this);
    };

    Array.prototype.toJSONString = function () {
        return s.array(this);
    };
})();
// 20060804 [msd] - encapsulate the eval() in case we ever needed to introduce a JSON parser
String.prototype.toObject = function() { // return an javascript object from a JSON string
    try {
        return eval("(" + this + ")");
		} 
	catch (e) {
		throw e
		return false;
		}
	}

function cleanString( a ) {
	return a.replace(/\\/g, "\\\\").replace(/"/g,'\\"').replace(/\\\n/g,"\\ \n").replace(/([^\\])(\s)?\n/g,"$1\\n" );
	}
	
function dtoDumpStateInfo(V, A, M, S) {
	var lcVerbose		= (V) ? V : "0" ; // Verbose 0=silent, 1=alert on fail, 2=alert on fail+success
	var lcMessage 		= (M) ? M : "DataObject State Info" ;
	var lcApplication 	= (A) ? A : "DataObject" ;
	var lcSeverity 		= (S) ? S : "100" ;

	var	lcWebService = "/common/ajax/LogStateInfo.asp" +
							"?Severity=" + lcSeverity + 
							"&Application=" + lcApplication +
							"&Message=" + lcMessage
	
	var err = false;
	try {
		var rv = dto.getURL( lcWebService, dto );
		var obj = rv.toObject();
		err = (obj.Errors.length > 0) ;
		}
	catch(e) {
		err = true;
		}

	if( lcVerbose=="0" ) {
		// do nothing, explicitly silent behavior
		}
	else {
		if( err ) {
			// ask user to send email
			var bdy = document.getElementsByTagName("body")[0];
			var dv = document.createElement("div");
			
	//		dv.setAttribute('style','background-color: white; position: absolute; top: 0; left: 0; height: 100%; width: 100%;');
			dv.setAttribute('style','background-color: white; position: absolute; top: 0; left: 0; height: 90%; width: 90%; padding: 5%;');
			bdy.appendChild(dv);
			
			var tn = document.createTextNode( "Problem sending error report: " );
			var h3 = document.createElement("h3");
			h3.appendChild( tn );
			dv.appendChild( h3 );
			
			var tn = document.createTextNode( "Please copy the selected text, then paste into an email to Helpdesk@pbp.com" );
			var lk = document.createElement("a");
			var lcSubject = 'SVR:' + lcSeverity + ' APP: ' + lcApplication + '  MSG: ' + lcMessage ;
			lk.setAttribute('href','mailto: Helpdesk@pbp.com?Subject=' + lcSubject + '&body=(Please paste the error report here)'  );
			lk.setAttribute('onclick', 'this.innerHTML = "Restart your browser to clear this error after sending the email"; ');
			lk.appendChild( tn );
			
			dv.appendChild( lk );
			
			var tn = document.createTextNode( dto.toJSONString() );
		    var ta = document.createElement("textarea");
			ta.setAttribute('style', 'width: 100%; height: 80%;');
			ta.setAttribute('readonly', 'readonly');
		    ta.appendChild(tn);
			
			dv.appendChild(ta);

			alert("Problem sending error report\n\nPlease copy and paste the following text into an email to the Helpdesk");
			
			ta.select();
			
			}
		else {
			if( lcVerbose=="2" ){
				// inform user of log ID
				var bdy = document.getElementsByTagName("body")[0];
				var dv = document.createElement("div");
				dv.setAttribute('style','background-color: white; position: absolute; top: 0; left: 0; height: 90%; width: 90%; padding: 5%;');
				bdy.appendChild(dv);
				
				var tn = document.createTextNode( "Error report has been logged" );
				var h3 = document.createElement("h3");
				h3.appendChild( tn );
				dv.appendChild( h3 );
				var tn = document.createTextNode( "Click here to refresh the page" );
				var lk = document.createElement("a");
				lk.setAttribute('href', window.location);
				//lk.setAttribute('onclick', 'window.location = window.location;');
				lk.appendChild( tn );
				
				dv.appendChild( lk );
				
				alert( "Error report has been logged\n\n" +
						"Logs0010Id = " + obj.Rows[0][0] + 
						"\n\nClick the link to refresh the page" )
				}
			}
		}
		
	}
	
