var browser_type = '';
if( navigator.userAgent.indexOf( 'Opera' ) != -1 )
   browser_type = 'Opera';
else if( navigator.userAgent.indexOf( 'Safari' ) != -1 )
   browser_type = 'Safari';
else if( navigator.userAgent.indexOf( 'Gecko' ) != -1 )
   browser_type = 'Gecko';
else if( navigator.userAgent.indexOf( 'MSIE' ) != -1 )
   browser_type = 'IE';
else
   browser_type = 'NS';

String.prototype.trim = function() {
  return this.replace(/^\s+|\s+$/g, '');
}

String.prototype.striphtml = function() {
	return this.replace(/(<([^>]+)>)/ig,"");
}

String.prototype.stripjs = function() {
	var tmp = this.replace(/(<script[^>]*>.*<\/script[^>]*>)*/ig,'');
	tmp = tmp.replace(/<script[^>]*>/ig,'');
	return tmp;
}

Number.prototype.format =  function(decimalNum, bolCommas) {
	if (isNaN(parseInt(this)))
		return "";
	var tmpNum = this;
	var iSign = this < 0 ? -1 : 1; /* Get sign of number*/

	/* Adjust number so only the specified number of numbers after the decimal point are shown.*/
	tmpNum *= Math.pow(10,decimalNum);
	tmpNum = Math.round(Math.abs(tmpNum))
	tmpNum /= Math.pow(10,decimalNum);
	tmpNum *= iSign; /* Readjust for sign*/

	/* Create a string object to do our formatting on*/
	var tmpNumStr = new String(tmpNum);

	/* See if we need to put in the commas*/
	if (bolCommas && (this >= 1000 || this <= -1000)) {
		var iStart = tmpNumStr.indexOf(".");
		if (iStart < 0)
			iStart = tmpNumStr.length;

		iStart -= 3;
		while (iStart >= 1) {
			tmpNumStr = tmpNumStr.substring(0,iStart) + "," + tmpNumStr.substring(iStart,tmpNumStr.length)
			iStart -= 3;
		}
	}

	return tmpNumStr; /* Return our formatted string!*/
}


if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}

Array.prototype.removeAllEntries = function(c) {
	for (var f=this.length-1; f>=0; f--) {
		if (this[f]==c) {
			this.splice(f,1);
		}
	}
}

if (typeof uneval != "function") {
	uneval = function  (o) {
		switch (typeof o) {
			case "undefined" : return "(void 0)";
			case "boolean"   : return String(o);
			case "number"    : return String(o);
			case "string"    : return '"' + o.replace(/"/g, '\\"') + '"';
			case "function"  : return "(" + o.toString() + ")";
			case "object"    :
				if (o == null) return "null";
				var type = Object.prototype.toString.call(o).match(/\[object (.+)\]/);
				if (!type) throw TypeError("unknown type:"+o);
				switch (type[1]) {
					case "Array":
						var ret = [];
						for (var i = 0, l = o.length; i < l; ret.push(arguments.callee(o[i++])));
						return "[" + ret.join(", ") + "]";
					case "Object":
						var ret = [];
						for (var i in o) {
							if (!o.hasOwnProperty(i)) continue;
							ret.push(arguments.callee(i) + ":" + arguments.callee(o[i]));
						}
						return "({" + ret.join(", ") + "})";
					case "Number":
						return "(new Number(" + o + "))";
					case "String":
						return "(new String(" + arguments.callee(o) + "))";
					case "Date":
						return "(new Date(" + o.getTime() + "))";
					default:
						if (o.toSource) return o.toSource();
						throw TypeError("unknown type:"+o);
				}
		}
	}
}

/*************
this function will take a string and split it into equal specified parts and return as array
**************/
function splitN(intext, splitlen) {
	var tmparr = new Array();
	var textLen = intext.length;
	if (textLen > splitlen) {
		var si = 0;
		var ei = splitlen;
		while (si < textLen) {
			if (ei > textLen)
				ei = textLen;
			tmparr.push(intext.substring(si, ei));
			si = ei;
			ei = ei + splitlen;
		}
	}	else {
		tmparr.push(intext);
	}
	return tmparr;
}

/*************
this function will take any object, expand and display the content to the browser)
**************/
function explain(obj,rec){
	var s = "";
	s += explaininner(obj,0,rec);
	alert(s);
}
/*************
this function is a recursive subset for the function above ... only call above function
**************/
function explaininner(obj,lvl,rec) {
	var rx = "";
	var sp = lvl+"";
	for (x=1; x<=lvl; x++) {
		sp+="    ";
	}
	for (var key in obj) {
		var k = obj[key];
	  if (typeof k.length == "number") {
			rx += "\n"+sp+"-"+key+":"+k.toString();
		} else if (typeof k == "object") {
			rx += "\n"+sp+"-"+key;
			if (rec || (!rec && lvl==0))
				rx += explaininner(k, lvl+1, rec);
		} else {
			rx += "\n"+sp+"-"+key+":"+k;
		}
	}
	return rx;
}

/*************
this removes x'' from a string
**************/
function rmxId(rstr){
	return rstr.substring(0,2)=="x'"?rstr.substring(2,rstr.length-1):rstr;
}

/*************
this adds x'' if necessary to a string
**************/
function xId(dstr){
	return dstr.substring(0,2)=="x'"?dstr:"x'"+dstr+"'";
}

function getWindowHeight() {
	var windowHeight=0;
	if (typeof(window.innerHeight)=='number')	{
		windowHeight=window.innerHeight;
	}	else {
		if (document.documentElement && document.documentElement.clientHeight){
			windowHeight = document.documentElement.clientHeight;
		} else {
			if (document.body && document.body.clientHeight) {
				windowHeight = document.body.clientHeight;
			}
		}
	}
	return windowHeight;
}

function getWindowWidth() {
	var windowWidth=0;
	if (typeof(window.innerWidth)=='number'){
		windowWidth=window.innerWidth;
	}	else {
		if (document.documentElement && document.documentElement.clientWidth)	{
			windowWidth = document.documentElement.clientWidth;
		}	else {
			if (document.body && document.body.clientWidth)	{
				windowWidth = document.body.clientWidth;
			}
		}
	}
	return windowWidth;
}

function changecss(theClass,element,value) {
	var cssRules;
	if (document.all) {
		cssRules = 'rules';
	}	else if (document.getElementById) {
		cssRules = 'cssRules';
	}
	for (var S = 0; S < document.styleSheets.length; S++){
		for (var R = 0; R < document.styleSheets[S][cssRules].length; R++) {
			if (document.styleSheets[S][cssRules][R].selectorText == theClass) {
				document.styleSheets[S][cssRules][R].style[element] = value;
			}
		}
	}
}

function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}

/*************
Formats the date with the given date mask. The mask is returned and the internal date is not altered.
**************/
Date.prototype.formatDate = function(strMask){
	/* Create the values for each part of the potential date mask.*/
	var x = this.getMonth()+1;
	var objParts = {
		"d": this.getDate(),
		"dd": (this.getDate().toString().length == 1) ? ("0" + this.getDate()) : this.getDate(),
		"ddd": [ "Sun","Mon","Tue","Wed","Thu","Fri","Sat" ][ this.getDay() ],
		"dddd": [ "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday" ][ this.getDay() ],
		"m": x,
		"mm": (x.toString().length == 1) ? ("0" + x) : x,
		"mmm": [ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" ][ this.getMonth() ],
		"mmmm": [ "January","February","March","April","May","June","July","August","September","October","November","December" ][ this.getMonth() ],
		"yy": this.getYear().toString().substring( 1, 3 ),
		"yyyy": this.getFullYear()
		}

	/* Check to see if we have special date formatting options.*/
	switch ( strMask ){
		case "short":
			return( objParts[ "m" ] + "/" + objParts[ "d" ] + "/" + objParts[ "yyyy" ] );
			break;

		case "medium":
			return( objParts[ "mmm" ] + " " + objParts[ "d" ] + ", " + objParts[ "yyyy" ] );
			break;

		case "long":
			return( objParts[ "mmmm" ] + " " + objParts[ "d" ] + ", " + objParts[ "yyyy" ] );
			break;

		case "full":
			return( objParts[ "dddd" ] + ", " + objParts[ "mmmm" ] + " " + objParts[ "d" ] + ", " + objParts[ "yyyy" ] );
			break;

		default:
			/* There was no special date formatting, so just use the mask.*/
			return(
				strMask.replace(
					new RegExp( "(d{1,4}|m{1,4}|y{4}|y{2})", "gi" ),
					function( $1 ){
						return( objParts[ $1 ] );
						})
				);
			break;
	}
}

/*************
generic time format
**************/
Date.prototype.formatTime = function(){
	var a_p = "";
	var curr_hour = this.getHours();
	if (curr_hour < 12)
		a_p = "AM";
	else
		a_p = "PM";
	if (curr_hour == 0)
		curr_hour = 12;
	if (curr_hour > 12)
		curr_hour = curr_hour - 12;
	var curr_min = this.getMinutes();
	curr_min = curr_min + "";
	if (curr_min.length == 1)
		curr_min = "0" + curr_min;
	return curr_hour+":"+curr_min+" "+a_p;
}

function whoCalledMe(a) {
 	alert("Called by: \n" + a.callee.caller.toString());
 	for (var x=0; x<a.length; x++) {
 		alert("Argument " + x + ": " + a[x]);
 	}
}

/*************
converts a string to be safe for db, js, html, tech_id, int, decimal, date
**************/
String.prototype.quote = function( quotetype, default_value )
{
   if( !default_value )
      default_value = '';

	/* Database quote: ' -> ''*/
	if( quotetype == 'db' )
	{
	   var tmp = '' + this;
		return tmp.replace(/\'/g,"''");
   }

	/* Javascript quote: ' -> \' and " -> \" and \n --> \\n and \r --> \\r*/
	else if( quotetype == 'js' )
	{
	   var tmp = '' + this;
		return tmp.replace(/\\/g, "\\\\").replace(/\'/g, "\\'").replace(/\"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
	}

   /* HTML quote: < to &lt; and > to &gt; and " to &quot; and & to &amp;*/
	else if( quotetype == 'html' )
	{
	   var tmp = '' + this;
	   return tmp.replace(/\</g, "&lt;").replace(/\>/g, "&gt;").replace(/\"/g, "&quot;").replace(/\&/g, "&amp;");
	}

	/* tech_id quote: make sure string is of format x'12345678901234567890123456'*/
	/* Returns "raw" tech_id on success, or blank string on failure*/
	else if( quotetype == 'tech_id' )
	{
	   var tmp = '' + this;
	   if( tmp.length != 26 && tmp.length != 29 )
	      return default_value;
	   tmp = rmxId( tmp );
	   for( var i = 0; i < 26; i++ )
	   {
	      var c = tmp.charAt(i);
	      if( c != '0' && c != '1' && c != '2' && c != '3' && c != '4' && c != '5' && c != '6' && c != '7' && c != '8' && c != '9' )
	         return default_value;
	   }
	   return xId(tmp);
	}

	/* int quote: make sure string only contains 0123456789-*/
	else if( quotetype == 'int' )
	{
	   var tmp = '' + this;
	   tmp = tmp.replace(/[^\d\-]/g,'');
	   var tmpint = parseInt( tmp );
	   if( isNaN( tmpint ) )
	      return default_value;
	   return tmpint;
	}

	/* decimal quote: make sure string only contains 0123456789-.*/
	else if( quotetype == 'decimal' )
	{
	   var tmp = '' + this;
	   tmp = tmp.replace(/[^\d\-\.]/g,'');
	   var tmpfloat = parseFloat( tmp );
	   if( isNaN( tmpfloat ) )
	      return default_value;
	   return tmpfloat;
	}

   /* date quote: accepts dates in any of these formats, with any delimiter character:*/
   /*             YYYY-MM-DD, MM-DD-YYYY, MM-DD-YY, YYYYMMDD, MMDDYY*/
   /* returns a blank string if date does not verify.*/
   else if( quotetype == 'date' )
   {
      var tmp = '' + this;
      tmp = tmp.trim().replace(/[\D]/g,'/');

	  /* make sure the user isn't submitting 00/00/0000.  CUR-3983 */
      zerotmp = tmp;
	  if (parseInt(zerotmp.replace(/\D/g,''),10) == 0)
		return '';

      if( tmp.length == 8 && tmp.indexOf('/') == -1 ) /* the date is in a format without delimiter characters*/
      {
         /* attempt to guess the proper date format*/
         if( tmp.charAt(0) == '2' && (tmp.charAt(1) == '0' || tmp.charAt(1) == '1' ) )
         {
            /* guessing that this is YYYY/MM/DD*/
            tmp = tmp.substr( 0, 4 ) + '/' + tmp.substr( 4, 2 ) + '/' + tmp.substr( 6, 2 );
         }
         /* Otherwise, assume MM/DD/YYYY or MM/DD/YY*/
         else
            tmp = tmp.substr( 0, 2 ) + '/' + tmp.substr( 2, 2 ) + '/' + tmp.substr( 4, 4 );
      }
      else if( tmp.length == 6 && tmp.indexOf('/') == -1 ) /* again, no delimiter characters*/
      {
         /* assume MM/DD/YY*/
         var tmpyear = parseInt( tmp.substr( 4, 2 ),10 );
         if( tmpyear < 75 )
            tmpyear += 2000;
         else
            tmpyear += 1900;
         tmp = tmp.substr( 0, 2 ) + '/' + tmp.substr( 2, 2 ) + '/' + tmpyear;
      }
      else if (tmp.match(/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{1,2}$/)) {
     		var tmpyear = parseInt(tmp.substr(tmp.lastIndexOf("/")+1).replace(/^[^1-9]/,''));
         if( tmpyear < 75 )
            tmpyear += 2000;
         else
            tmpyear += 1900;
         tmp = tmp.substr( 0, tmp.indexOf("/") ) +"/"+ tmp.substr(  tmp.indexOf("/")+1, (tmp.lastIndexOf("/")- (tmp.indexOf("/")+1)))+"/" + tmpyear;
      }

      var tmpdate = new Date( tmp );
      if( isNaN( tmpdate ) )
         return default_value;
      else{
		var tmpyear = tmpdate.getFullYear();
		var stddate = (tmpdate.getMonth()+1) + '/' + tmpdate.getDate() + '/' + tmpyear;
		return stddate;
	}
   }
}

/*************
initialCaps - Capitalizes the first letter of all words in a String
**************/
String.prototype.initialCaps = function(){
	return this.replace( /\b\w+\b/g, function (word) {
		return word.substring(0,1).toUpperCase() + 	word.substring(1).toLowerCase()
	});
}


/*************
MASK FUNCTION - used to format strings to specifications - http://jira.fbsdata.com/confluence/x/RR8
**************/
String.prototype.mask = function(mask) {
	if (!mask) return this;  // return original string if no mask is passed in

	// variables
	var newString = '';
	var reverse = (mask.match(/\!$/)) ? true : false ; // if there is a ! at the end of the mask, this must be processed from right to left

	// if reverse has been established, remove the ! at the end of the mask
	if (reverse)
		mask = mask.substring(0, mask.length-1);

	// establish beginning and ending of loop
	var loopPosition = (reverse) ? mask.length-1 : 0 ;
	var loopEnd = (reverse) ? -1 : mask.length ;
	var stringPosition = (reverse) ? this.length-1 : 0 ;
	var stringEnd = (reverse) ? -1 : this.length ;
	var caseModifier = null; // used if < or > are invoked, forcing characters to be all lower or upper case
	var absoluteModifier = false // used to detect (\\), which denote that then next character must be present
	var absoluteCharacter = null; // used as a placeholder to reduce code

	// setup loop
	while (loopPosition != loopEnd) {

		// find the next characters in the mask and the string
		var stringChar = (stringPosition == stringEnd) ? null : this.charAt(stringPosition) ;
		var maskChar = mask.charAt(loopPosition);

		// if this is reverse, look ahead one character to see if an absoute modifier is in place (\\)
		// also: don't check the first character in the mask, nothing can possibly proceed it
		if (reverse && loopPosition-1 != loopPosition && mask.charAt(loopPosition-1) == '\\')
			absoluteModifier = true;

		// if this is an absolute character (escaped by \\), set a placeholder variable and force the switch statement to default
		if (absoluteModifier) {
			absoluteCharacter = maskChar;
			maskChar = 'N';
		}

		// iterate here, as we may have a situation where a continue is called
		(reverse) ? loopPosition-- : loopPosition++ ;

		// process the mask character
		switch (maskChar) {

			case '>': // all characters after this must be uppercase
				caseModifier = 'uppercase';
				continue;
				break;

			case '<': // all characters after this must be lowercase
				caseModifier = 'lowercase';
				continue;
				break;

			case '\\': // the next character must be an exact match, used to escape
				absoluteModifier = (reverse) ? false : true;
				continue;
				break;

			case '0': // required digit
				if (stringChar) {
					var stringMatch = stringChar.match(/\d/);
					var stringToAdd = (stringMatch) ? stringChar : '0' ;
					newString = (reverse) ? stringToAdd + newString : newString + stringToAdd ;
					(reverse) ? stringPosition-- : stringPosition++ ;
				}
				else newString = (reverse) ? '0' + newString : newString + '0' ; // force zero if no digit is present
				break;

			case '9': // optional digit
				if (stringChar) {
					var stringMatch = stringChar.match(/\d/);
					if (stringMatch) {
						newString = (reverse) ? stringChar + newString : newString + stringChar ;
						(reverse) ? stringPosition-- : stringPosition++ ;
					}
				}
				break;

			case '#': // required digit, space, plus, or minus
				if (stringChar) {
					var stringMatch = stringChar.match(/\d|-|\+|\s/);
					var stringToAdd = (stringMatch) ? stringChar : ' ' ;
					newString = (reverse) ? stringToAdd + newString : newString + stringToAdd ;
					(reverse) ? stringPosition-- : stringPosition++ ;
				}
				else newString = (reverse) ? '0' + newString : newString + '0' ; // force zero if no digit is present
				break;

			case 'L': // required letter
				if (stringChar) {
					var stringMatch = stringChar.match(/[a-z]|[A-Z]/);
					if (stringMatch) {

						// handle any case modifiers (<) or (>)
						if (caseModifier == 'lowercase')
							newString = (reverse) ? stringChar.toLowerCase() + newString : newString + stringChar.toLowerCase() ;
						else if (caseModifier == 'uppercase')
							newString = (reverse) ? stringChar.toUpperCase() + newString : newString + stringChar.toUpperCase() ;
						else
							newString = (reverse) ? stringChar + newString : newString + stringChar ;

						(reverse) ? stringPosition-- : stringPosition++ ;
					}
					else { // force X if no letter is present
						if (caseModifier == 'lowercase')
							newString = (reverse) ? 'x' + newString : newString + 'x' ;
						else
							newString = (reverse) ? 'X' + newString : newString + 'X' ;
					}
				}
				break;

			case '?': // optional letter
				if (stringChar) {
					var stringMatch = stringChar.match(/[a-z]|[A-Z]/);
					if (stringMatch) {

						// handle any case modifiers (<) or (>)
						if (caseModifier == 'lowercase')
							newString = (reverse) ? stringChar.toLowerCase() + newString : newString + stringChar.toLowerCase() ;
						else if (caseModifier == 'uppercase')
							newString = (reverse) ? stringChar.toUpperCase() + newString : newString + stringChar.toUpperCase() ;
						else
							newString = (reverse) ? stringChar + newString : newString + stringChar ;

						(reverse) ? stringPosition-- : stringPosition++ ;
					}
				}
				break;

			case 'A': // required letter or digit
				if (stringChar) {
					var stringMatch = stringChar.match(/[a-z]|[A-Z]|\d/);
					if (stringMatch) {

						// handle any case modifiers (<) or (>)
						if (caseModifier == 'lowercase')
							newString = (reverse) ? stringChar.toLowerCase() + newString : newString + stringChar.toLowerCase() ;
						else if (caseModifier == 'uppercase')
							newString = (reverse) ? stringChar.toUpperCase() + newString : newString + stringChar.toUpperCase() ;
						else
							newString = (reverse) ? stringChar + newString : newString + stringChar ;

						(reverse) ? stringPosition-- : stringPosition++ ;
					}
					else { // force X if no letter is present
						if (caseModifier == 'lowercase')
							newString = (reverse) ? 'x' + newString : newString + 'x' ;
						else
							newString = (reverse) ? 'X' + newString : newString + 'X' ;
					}
				}
				break;

			case 'a': // optional letter or digit
				if (stringChar) {
					var stringMatch = stringChar.match(/[a-z]|[A-Z]|\d/);
					if (stringMatch) {

						// handle any case modifiers (<) or (>)
						if (caseModifier == 'lowercase')
							newString = (reverse) ? stringChar.toLowerCase() + newString : newString + stringChar.toLowerCase() ;
						else if (caseModifier == 'uppercase')
							newString = (reverse) ? stringChar.toUpperCase() + newString : newString + stringChar.toUpperCase() ;
						else
							newString = (reverse) ? stringChar + newString : newString + stringChar ;

						(reverse) ? stringPosition-- : stringPosition++ ;
					}
				}
				break;

			case '&': // required character or space
				if (stringChar) {
					var stringMatch = stringChar.match(/./);
					if (stringMatch) {

						// handle any case modifiers (<) or (>)
						if (caseModifier == 'lowercase')
							newString = (reverse) ? stringChar.toLowerCase() + newString : newString + stringChar.toLowerCase() ;
						else if (caseModifier == 'uppercase')
							newString = (reverse) ? stringChar.toUpperCase() + newString : newString + stringChar.toUpperCase() ;
						else
							newString = (reverse) ? stringChar + newString : newString + stringChar ;

						(reverse) ? stringPosition-- : stringPosition++ ;
					}
					else { // force X if no letter is present
						if (caseModifier == 'lowercase')
							newString = (reverse) ? 'x' + newString : newString + 'x' ;
						else
							newString = (reverse) ? 'X' + newString : newString + 'X' ;
					}
				}
				break;

			case 'C': // optional character or space
				if (stringChar) {
					var stringMatch = stringChar.match(/./);
					if (stringMatch) {

						// handle any case modifiers (<) or (>)
						if (caseModifier == 'lowercase')
							newString = (reverse) ? stringChar.toLowerCase() + newString : newString + stringChar.toLowerCase() ;
						else if (caseModifier == 'uppercase')
							newString = (reverse) ? stringChar.toUpperCase() + newString : newString + stringChar.toUpperCase() ;
						else
							newString = (reverse) ? stringChar + newString : newString + stringChar ;

						(reverse) ? stringPosition-- : stringPosition++ ;
					}
				}
				break;

			default: // exact match

				// if this is an absolute character (escaped by \\), use the placeholder variable and reset the absolute variables
				if (absoluteModifier) {
					maskChar = absoluteCharacter;
					absoluteModifier = false;
					absoluteCharacter = null;
				}

				if (stringChar) {
					var stringMatch = (stringChar.indexOf(maskChar) != -1);
					if (stringMatch) {
						newString = (reverse) ? stringChar + newString : newString + stringChar ;
						(reverse) ? stringPosition-- : stringPosition++ ;
					}
					else
						newString = (reverse) ? maskChar + newString : newString + maskChar ;
				}
				else
					newString = (reverse) ? maskChar + newString : newString + maskChar ;

				break;
		}
	}

	return newString;
}

/**
 * Loads a JavaScript or CSS file late, after the page has loaded.
 * @param fNm {String} path of file to load
 * @param fTyp {String} type of file to load "js" or "css"
 * @param tmOut {Integer} delay, in milliseconds (optional)
 */
var lazyLoad = function(){
  var loadedFiles=[];
  return function(fNm,fTyp,tmOut){
    if(!fNm || !fTyp){return;}
    var isLoaded=false;
    for(var i=0;i<loadedFiles.length;i++){if(loadedFiles[i]==fNm){isLoaded=true;}}
    if(!isLoaded){
      tmOut=((tmOut)?tmOut:0);
      loadedFiles.push(fNm);
      if(fTyp=='js'){
        var fToken=document.createElement('script');
        fToken.setAttribute('type','text/javascript');
        fToken.setAttribute('src',fNm);
      }
      else if(fTyp=='css'){
        var fToken=document.createElement('link');
        fToken.setAttribute('rel','stylesheet');
        fToken.setAttribute('type','text/css');
        fToken.setAttribute('href',fNm);
      }
      if(typeof fToken!='undefined'){
        cmd=function(){document.getElementsByTagName('head')[0].appendChild(fToken);}
        setTimeout(cmd,tmOut);
      }
    }
  };
}();

function openNewMsg(inObj,showReceived){
	var done=false;
	try{if(parent.parent.parent&&parent.parent.parent.MSGp){done=true; parent.parent.parent.MSGp.showNewMsgPanel(inObj,showReceived);}}
	catch( e ){}
	if( !done ){
		try{if(parent.parent&&parent.parent.MSGp){done=true; parent.parent.MSGp.showNewMsgPanel(inObj,showReceived);}}
		catch( e ){}
	}
	if( !done ){try{if(parent&&parent.MSGp){done=true; parent.MSGp.showNewMsgPanel(inObj,showReceived);}}
	catch( e ){}
	}
	if( !done ){
		try{if(MSGp){done=true; MSGp.showNewMsgPanel(inObj,showReceived);}}
	catch( e ){}
	}
	if( !done ){
		if( showReceived === undefined ){ showReceived = false; }
		addMissingDivs( 'openNewMsg',inObj,showReceived );
	}
	return
}

function showUiFeedback( msgIn, typ, timer, prevId )
{
	var done = false;
	var tmpId = Math.floor( Math.random() * 1000000000000 );
	try{if(parent.parent.parent&&parent.parent.parent.MSGp){done=true; parent.parent.parent.MSGp.showUiFeedbackPanel(msgIn,typ,timer,prevId,tmpId);}}
	catch( e ){}
	if( !done ){
		try{if(parent.parent&&parent.parent.MSGp){done=true; parent.parent.MSGp.showUiFeedbackPanel(msgIn,typ,timer,prevId,tmpId);}}
		catch( e ){}
	}
	if( !done ){try{if(parent&&parent.MSGp){done=true; parent.MSGp.showUiFeedbackPanel(msgIn,typ,timer,prevId,tmpId);}}
	catch( e ){}
	}
	if( !done ){
		try{if(MSGp){done=true; MSGp.showUiFeedbackPanel(msgIn,typ,timer,prevId,tmpId);}}
	catch( e ){}
	}
	if( !done ){
		arg1 = ( ( msgIn === undefined ) ? '' : msgIn );
		arg2 = ( ( typ === undefined ) ? '' : typ );
		arg3 = ( ( timer === undefined ) ? '' : prevId );
		arg4 = ( ( prevId === undefined ) ? tmpId : prevId );
		addMissingDivs( 'showUiFeedback', arg1, arg2, arg3, arg4 );
	}
	return tmpId;
}
function closeUiFeedback( msgIdIn )
{
	var done = false;
	try{if(parent.parent.parent&&parent.parent.parent.MSGp){done=true; parent.parent.parent.MSGp.closeUiFeedbackPanel(msgIdIn);}}
	catch( e ){}
	if( !done ){
		try{if(parent.parent&&parent.parent.MSGp){done=true; parent.parent.MSGp.closeUiFeedbackPanel(msgIdIn);}}
		catch( e ){}
	}
	if( !done ){try{if(parent&&parent.MSGp){done=true; parent.MSGp.closeUiFeedbackPanel(msgIdIn);}}
	catch( e ){}
	}
	if( !done ){
		try{if(MSGp){MSGp.closeUiFeedbackPanel(msgIdIn);}}
	catch( e ){}
	}
	return;
}

function showLoadingPnl(txtIn)
{
	var done = false;
	try{if(parent.parent.parent&&parent.parent.parent.MSGp){done=true; parent.parent.parent.MSGp.showLoad(txtIn);}}
	catch( e ){}
	if( !done ){
		try{if(parent.parent&&parent.parent.MSGp){done=true; parent.parent.MSGp.showLoad(txtIn);}}
		catch( e ){}
	}
	if( !done ){try{if(parent&&parent.MSGp){done=true; parent.MSGp.showLoad(txtIn);}}
	catch( e ){}
	}
	if( !done ){
		try{if(MSGp){done=true; MSGp.showLoad(txtIn);}}
	catch( e ){}
	}
	if( !done ){
		arg1 = ( ( txtIn === undefined ) ? '' : txtIn );
		addMissingDivs( 'showLoadingPnl', arg1 );
	}
	return;
}

function hideLoadingPnl()
{
	var done = false;
	try{if(parent.parent.parent&&parent.parent.parent.MSGp){done=true; parent.parent.parent.MSGp.hideLoad();}}
	catch( e ){}
	if( !done ){
		try{if(parent.parent&&parent.parent.MSGp){done=true; parent.parent.MSGp.hideLoad();}}
		catch( e ){}
	}
	if( !done ){try{if(parent&&parent.MSGp){done=true; parent.MSGp.hideLoad();}}
	catch( e ){}
	}
	if( !done ){
		try{if(MSGp){MSGp.hideLoad();}}
	catch( e ){}
	}
	return;
}

var msgObjHold = {};

var addMissingDivs = function()
{
	var appendDivsCalled = false;
	var cntTries = 0;
	return function( reCall, arg1, arg2, arg3, arg4 )
	{
		if( reCall === undefined || reCall == '' ){ return; }
		in1 = ( ( arg1 === undefined ) ? '' : arg1 );
		in2 = ( ( arg2 === undefined ) ? '' : arg2 );
		in3 = ( ( arg3 === undefined ) ? '' : arg3 );
		in4 = ( ( arg4 === undefined ) ? '' : arg4 );
		if( appendDivsCalled == false )
		{
			var prtlVars = '';
			var u1 = document.URL;
			if( u1.search( '&portal=true' ) )
			{
				var indx1 = u1.indexOf( '&memid=port_' );
				var u2 = u1.substring( indx1 + 12 );
				indx1 = u2.indexOf( '_' );
				var clId = u2.substring( 0, indx1 );
				u2 = u2.substring( indx1 + 1 );
				indx1 = u2.indexOf( '_' );
				var tId = u2.substring( 0, indx1 );
				prtlVars = '&client_lookup=true&client_id=' + clId + '&tech_id=' + tId;
			}
			if( reCall == 'openNewMsg' ){ msgObjHold = in1; in1 = ''; }
			var msgDiv = document.createElement( 'div' );
			msgDiv.id = 'MSGpNewMsgPnl';
			msgDiv.style.display = 'none';
			document.getElementsByTagName('Body')[0].appendChild( msgDiv );
			var warnDiv = document.createElement( 'div' );
			warnDiv.id = 'MSGpWarningPnl';
			warnDiv.style.display = 'none';
			document.getElementsByTagName('Body')[0].appendChild( warnDiv );
			var loadDiv = document.createElement( 'div' );
			loadDiv.id = 'MSGpLoadingMsg';
			loadDiv.style.display = 'none';
			document.getElementsByTagName('BODY')[0].appendChild( loadDiv );
			var iA = [ 'cmd=srv+dao/msg/api.html&funcCall=loadMsgDivs' ];
			iA.push( '&callBack=' + reCall + '&arg1=' + in1.toString() + '&arg2=' + in2 + '&arg3=' + in3 + '&arg4=' + in4 );
			if( prtlVars != '' ){ iA.push( prtlVars ); }
			loadJavaScriptDoc( 'querystring', 'mainmenu.cgi', iA.join( '' ), false, false )
			appendDivsCalled = true;
		}
		else
		{
			if( cntTries < 10 )
			{
				if( reCall == 'openNewMsg' ){ var cmd = reCall + '( msgObjHold,' + in2 + ')'; }
				else{ var cmd = reCall + '(' + in1 + ',' + in2 + ',' + in3 + ',' + in4 + ')'; }
				setTimeout( cmd, 1000 );
				cntTries ++;
			}
		}
	};
}();

function loadMissingFiles( doCall, arg1, arg2, arg3, arg4, fileVer, reqVals, rcpStr )
{
	var msgScript = document.createElement( 'script' );
	msgScript.type = 'text/javascript';
	msgScript.charset = 'utf-8';
	var s = [];
	s.push( 'lazyLoad( "' + fileVer['newMsgPaneljs'] + '","js",0 ); ' );
	s.push( 'lazyLoad( "' + fileVer['newMsgPanelcss'] + '","css",200 ); ' );
	s.push( 'lazyLoad( "' + fileVer['lookup'] + '","js",400 ); ' );
	s.push( 'lazyLoad( "' + fileVer['validate'] + '","js",600 ); ' );
	s.push( 'lazyLoad( "' + fileVer['convert'] + '","js",800 ); ' );
//	s.push( 'lazyLoad( "' + fileVer['popcalendar'] + '","js",1000 ); ' );
	s.push( 'var extShwgs = ' + reqVals['extShwgs'] + ';' );
	s.push( 'var sndLoc = "' + reqVals['sndLoc'] + '";' );
	s.push( 'var sndId = "' + reqVals['sndId'] + '";' );
	s.push( 'var sndTyp = "' + reqVals['sndTyp'] + '";' );
	s.push( 'var sndNm = "' + reqVals['sndNm'] + '";' );
	s.push( 'var sndMaId = "' + reqVals['sndMaId'] + '";' );
	s.push( 'var isTmMem = ' + reqVals['isTmMem'] + ';' );
	s.push( 'var tmId = "' + reqVals['tmId'] + '";' );
	s.push( 'var tmNm = "' + reqVals['tmNm'] + '";' );
	s.push( 'var picsrv = "' + reqVals['picsrv'] + '";' );
	if( rcpStr !== undefined )
	{
		s.push( "var clientId = '" + reqVals['sndId'] + "';" );
		s.push( "var oObj = { id:'" + rcpStr['id'] + "', typ:'" + rcpStr['typ'] + "', nm:'" + rcpStr['nm'] + "', " );
		s.push( "bsCd:'" + rcpStr['bsCd'].replace( /'/g, "\\'" ) + "', gpId:'" + rcpStr['gpId'] + "', gpNm:'" + rcpStr['gpNm'] + "', " );
		s.push( "maId:'" + rcpStr['maId'] + "', maNm:'" + rcpStr['maNm'] + "', maCode:'" + rcpStr['maCode'] + "' };" );
	}
	msgScript.text = s.join( '' );
	document.getElementsByTagName('BODY')[0].appendChild( msgScript );
	if( doCall == 'openNewMsg' )
	{ var cmd = doCall + '( msgObjHold,' + arg2 + ')'; }
	else{ var cmd = doCall + '(' + arg1 + ',' + arg2 + ',' + arg3 + ',' + arg4 + ')'; }
	setTimeout( cmd, 1000 );
}

