var qasPopupSettings = "scrollbars=no,resizable=yes,width=540,height=560";

//Add events to <body onLoad="">
function addLoadEvent(func) {
	/** http://simon.incutio.com/archive/2004/05/26/addLoadEvent **/
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

function loadContents(destinationID, url) {
	loadContentsWithIcon(null, destinationID, url);
}

function loadContentsWithIcon(loadingImageID, destinationID, url) {
	var failed = false;
	var myAjax = new Ajax.Request(
	url,
	{
		method: 'get',
		onFailure: function(request) { 
			($(destinationID)).innerHTML = "Failed to load contents dynamically.";// + request.responseText); 
			failed = true;
			if (loadingImageID != null) {
				// Hide loading animation
				$(loadingImageID).style.display = 'none';
			}
		},
		onComplete: function(request) { 
			if (!failed && $(destinationID))
			($(destinationID)).innerHTML = request.responseText;
			if (loadingImageID != null) {
				// Hide loading animation
				$(loadingImageID).style.display = 'none';
			}
		}
	});
	
	if (loadingImageID != null) {
		// Show loading animation
		$(loadingImageID).style.display = 'block';
	}
}

/**
This is a more efficient implementation of getElementsByClassName borrowed from
http://lhorie.blogspot.com/2007/03/getelementsbyclassname-speed.html
**/
var getElementsByClassName = function(className, parentNode) {
    var results = [];
    //if (document.getElementsByClassName) document.getElementsByClassName(className,parentNode);//this is the code for FF3. Prototype 1.5 doesn't play nice with this code, though.
    if (document.evaluate) {
        var query = document.evaluate(".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]", parentNode
                || document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
        for (var i = 0, length = query.snapshotLength; i < length; i++) results.push(query.snapshotItem(i));
    }
    else { //IE
        var nodes = (parentNode || document).getElementsByTagName("*");
        for (var i = 0, j = 0, length = nodes.length; i < length; i++) {
            var nodes_i = nodes[i];
            var nodeIString = " " + nodes_i + " ";
            if (nodeIString.indexOf("http") == 1) {
                //Cant use toString() in IE on hyperlinks because it returns the URL, not the DOM Node
                if (nodes_i.className == className) {
                    results[j++] = nodes_i;
                }
            } else if (nodeIString.indexOf(" " + className + " ") > -1) {
                results[j++] = nodes_i;
            } else if (nodes_i.className == className) {
                results[j++] = nodes_i;
            } else if (nodes_i.className.indexOf(className) >= 0) {
				results[j++] = nodes_i;
			}
        }
    }
    return results;
};

/**
Based on the getElementsByClassName above, this function crams the results into an object that can be used as a hashtable.
This is much faster than a for loop and getElementById's!!!
**/
function getHashedElementsByClassName(className, parentNode) {
    var msgCount = 0;
    var resultHash = new Object;
    //if (document.getElementsByClassName) document.getElementsByClassName(className,parentNode);//this is the code for FF3. Prototype 1.5 doesn't play nice with this code, though.
    if (document.evaluate) {
        var query = document.evaluate(".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]", parentNode
                || document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
        for (var i = 0, length = query.snapshotLength; i < length; i++) {
            var elemID = query.snapshotItem(i).id;
            if (elemID) {
                resultHash[query.snapshotItem(i).id] = query.snapshotItem(i);
            }
        }
    }
    else {
        var nodes = (parentNode || document).getElementsByTagName("*");
        for (var i = 0, j = 0, length = nodes.length; i < length; i++) {
            var nodes_i = nodes[i];
			var nodeIString = " " + nodes_i + " ";		
			
			if (nodeIString.indexOf("http") == 1) {
				if (nodes_i.className == className) {
					var elemID = nodes_i.id;
	                if (elemID)
    	                resultHash[nodes_i.id] = nodes_i;
                }
			} else if (nodeIString == ' [object] ') { //IE sometimes doesnt do toString() properly
				if (nodes_i.className == className){
					var elemID = nodes_i.id;
	                if (elemID)
    	                resultHash[nodes_i.id] = nodes_i;
				}
			} else if (nodeIString.indexOf(" " + className + " ") > -1) {
                var elemID = nodes_i.id;
                if (elemID) {
                    resultHash[nodes_i.id] = nodes_i;
                }
            }
        }
    }
    return resultHash;
};

// Addresses a problem related to applying a JavaScript onchange function to an html select-box.
// If a JavaScript onchange function has been tied to a select-box and either the up/down arrow keys
// or scroll-wheel on the mouse are used when the select-box has focus then the onchange function
// will be executed for each item in the list that you scroll through.
// The function below uses a 750ms timer to prevent multiple onchange functions from being called.
// After an option is selected the safeOnChange function will wait for 750ms and if another option
// has not been chosen it will execute the code passed into it. This introduces a tiny delay that
// the user may or may not notice and you can tweak it by passing in a different milliseconds value.
// (Credited to the following article - http://www.netlobo.com/javascript_select_onchange.html)

// executes an onchange function after 750ms (or specified delay)
function safeOnChange( code, delay )
{
	delay = delay || 750;
	window.clearTimeout( soc_id );
	soc_id = window.setTimeout( code, delay );
}
// global timer ID for the safeOnChange1 function.
var soc_id = null;

function isInteger(theValue) {
	if (theValue == '')
		return false;
	for (i=0; i< theValue.length; i ++) {
		if (theValue.charAt(i) < "0")
			return false;
		if (theValue.charAt(i) > "9")
			return false;
	}
	return true;
}

function retrieveDynamicContent(url, destinationID) {
	retrieveDynamicContentWithCallback(null, url, destinationID);
}

function retrieveDynamicContentWithIcon(loadingImageID, url, destinationID) {
	//OVERLOAD addLoadEvent as it wont trigger from dynamic refresh.
	//addLoadEvent returning to normal will rely on a full page refresh.
	addLoadEvent = function(x) { x(); };
	
	var myAjax = new Ajax.Request(
	url,
	{
		method: 'get',
		onFailure: function(request) { 
			if (loadingImageID != null) {
				// Hide loading animation
				$(loadingImageID).style.display = 'none';
			}
			alert("Failed to load contents dynamically."); 
		},
		onComplete: function(request) { 
			//may need to add <script> tags and evaluate others
			launchJavascript(request.responseText);
			($(destinationID)).innerHTML = request.responseText;
			
			if (loadingImageID != null) {
				// Hide loading animation
				$(loadingImageID).style.display = 'none';
			}
		}
	});
	
	if (loadingImageID != null) {
		// Show loading animation
		$(loadingImageID).style.display = 'block';
	}
}
//http://rabaix.net/index.php/en/articles/issues_developing_ajax_libraries
//Had to add \r
function launchJavascript(responseText) {
  // RegExp from prototype.sonio.net
  var ScriptFragment = '(?:<script.*?>)((\n|.|\r)*?)(?:</script>)';          
  var scriptTagRegEx = new RegExp(ScriptFragment, 'img');
  var scripts  = responseText.match(scriptTagRegEx);
	
    if(scripts) {
        var js = '';
        for(var s = 0; s < scripts.length; s++) {
            var match2 = new RegExp(ScriptFragment, 'im');
			result = scripts[s].match(match2);
			if (result != null) {
	            js += result[1];
			}
        }
        eval(js);
    }
}
// Trim both ends of string
function trimString(sInString) {
  sInString = sInString.replace( /^\s+/g, "" );// strip leading
  return sInString.replace( /\s+$/g, "" );// strip trailing
}
// Trim leading end of string
function trimStringLeading(sInString) {
  return sInString.replace( /^\s+/g, "" );// strip leading
}
// Trim trailing end of string
function trimStringTrailing(sInString) {
  return sInString.replace( /\s+$/g, "" );// strip trailing
}

//Detect if the enter key has been hit
//example use: onKeyPress=return checkEnter(event?event.keyCode:e.which, 'categorySearch()')
function checkEnter(keycode, alternativeFunction){ //e is event object passed from function invocation
	if (keycode == 13) {	
		eval(alternativeFunction); //execute something else instead of acknoledging enter
		return false;
	}
	return true;
}

//Normally we use Ajax.Request, but that is restricted to context relative calls.
//This method will allow you to call anything that is server relative.
function getHTTPObject() { 
	var xhr = false;
	if (window.XMLHttpRequest) {
		xhr = new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		try {
			xhr = new ActiveXObject("Msxml2.XMLHTTP");
		} catch(e) {
			try {
				xhr = new ActiveXObject("Microsoft.XMLHTTP");
			} catch(e2) {
				xhr = false;
			}
		}
	}
	return xhr;
}
/*************************************************************************
					SPELL CHECKER
					******************************************************/
function openSpellChecker(textarea, functionToCall) {
	
	// example 1. 
	// Pass in the text inputs or textarea inputs that you 
	// want to spell-check to the object's constructor,
	// then call the openChecker() method.
	var speller = new spellChecker(textarea);
	if (functionToCall) {
		speller.setFunctionToCallOnClose(functionToCall);
	}
	speller.openChecker();
}

/*
	Does a check to see whether there are any errors but doesnt display the check spelling console.
*/
function isThereSpellingErrors(server, textarea) {
	errors = false;
	
	var speller = new spellChecker();
	var request = getHTTPObject(); //util.js
	if (request) {
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
				if (request.status == 200 || request.status == 304) {
					result = request.responseText;
					if (result.indexOf("words[0][0]") > 0) {
						 //There are spelling mistakes
						 errors = true;
					}
				} else {
					alert("Spell Check failed");
				}
			}
		};
		try {
			request.open("POST", server + speller.spellCheckScript, false);
			request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			request.send("textinputs[]=" + textarea.value);
		} catch (e) {
			alert("Your spelling cannot be checked at this time. " + e);
			errors = false;
		}
		return errors;
	}
}		

/******************************************************/
//					GENERIC HASH MAP
/******************************************************/
function KeyValue( key, value ) {
    this.key = key;
    this.value = value;
}

function Map() {
    this.array = new Array();
}

Map.prototype.put = function( key, value ) {
    if( ( typeof key != "undefined" ) && ( typeof value != "undefined" ) )
    {
        this.array[this.array.length] = new KeyValue( key, value );
    }
}

Map.prototype.get = function( key ) {
    for( var k = 0 ; k < this.array.length ; k++ )
    {
        if( this.array[k].key == key ) {
            return this.array[k].value;
        }
    }
    return "";
}

Map.prototype.getAll = function() {
    return this.array;
}

Map.prototype.remove = function(key) {
	newArray = new Array();
    for( var k = 0 ; k < this.array.length ; k++ ) {
        if( this.array[k].key != key ) {
            newArray[newArray.length] = this.array[k];
        }
    }
	this.array = newArray;
}

function aimAssetPagerReload(offset) {
	params = "pager.offset=" + offset;
	var myAjax = new Ajax.Request(
		thecontextpath + '/workOrders/link/am/lightboxPager.jsp',
		{
			method: 'get',
			parameters: params,
			 
			onComplete: function (request) {
				$('aim-search-results').innerHTML = request.responseText;
				$('aim-link-' + offset).focus();
			}
		});
	return false;
}
function buildLoadingImage(){
	loadingElement = document.createElement('img');
	loadingElement.setAttribute('src', webContextPath + '/icons/loading.gif');
	loadingElement.setAttribute('alt', 'loading');
	//loadingElement.setAttribute('class', 'loading'); this class has bg image so it appears twice
	loadingElement.setAttribute('id','temp-loading-image');
	loadingElement.style.display = 'inline';
	return loadingElement;
}

function evaluateResponseTextScripts(responseText) {
	charactersRemain = true;
	while(charactersRemain) {
		start = responseText.indexOf('<script') + 31;
		end = responseText.indexOf('</script>');
		if (start > -1 && end > -1) {
			scriptText = responseText.substring(start, end);
	    	eval(scriptText);
	    	responseText = responseText.substring(end + 9);
		} else {
			charactersRemain = false;
		}
	}
}
function launchAuthorityProgramInline(loadingImageId, params) {
	loader = $(loadingImageId);
	if (loader)
		loader.style.display = 'inline';
				
	params = params + "&picToHide=" + loadingImageId;
	var myAjax = new Ajax.Request(webContextPath + '/authorityInline.do',	{
		method: 'post',
		parameters: params,
		onFailure: function(request) { 
			window.alert("A problem has occurred.")
			},
		onComplete: function(response) {
			whatnext = trimString(response.responseText);
			eval(whatnext);
			}
		});
}

/* 4GL Printer Preferences */
var printerSelectionPopup;
function savePrinterPreference(printForm) {
       //Confirm which printer to use on program launch?
       var printerPrompt = printForm.confirmPrinterOnLaunch.checked;

       printerSelectionPopup.deactivate();

       var now = new Date();
       var params = "ajax=true&saved=true&confirmPrinterOnLaunch=" + printerPrompt + "&time=" + now.getTime();
       var myAjax = new Ajax.Request(webContextPath + '/updateCurrentPrinterPrompt.do',
       {
           method: 'get',
           parameters: params,
           onFailure: function(request) {
             searchResultsArea.innerHTML = "Error " + request.responseText;
               return false;

           }
           ,
           onComplete: function(request) {
               printerSelectionPopup.deactivate();
               return false;
           }
       });

       launch();
   }

function autosizeFrame(iframe) {
	var getFFVersion=navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox")).split("/")[1]
	var FFextraHeight=parseFloat(getFFVersion)>=0.1? 16 : 0 //extra height in px to add to iframe in FireFox 1.0+ browsers
		
	if (iframe.contentDocument) // firefox
	{
		iframe.height = 1;
		iframe.height = iframe.contentDocument.documentElement.scrollHeight + FFextraHeight + 12;
	}
	else // IE
	{
		iframe.height = 1;
		iframe.style.height = iframe.contentWindow.document.body.scrollHeight + FFextraHeight + 12;
	}
}
/* 
	HIDE/SHOW COLUMNS IN A TABLE
	cell is the hyperlink that contains the +/- icon
*/
	function hideColumn(theFunction, columnClass, cell) {
		var panelUpLinks = $A(getElementsByClassName(columnClass));
					  panelUpLinks.each(function(panelUpLink) {
												 panelUpLink.style.display = 'none';
												 });
		$(columnClass + "-header").style.display = 'none';										 
		cell.innerHTML = "<img src='" + webContextPath + "/icons/show-column.png' />";
		cell.onclick=function() {
						showColumn(columnClass, cell);
						return false;
		}; //onclick should be overridden by your javascript
		cell.setAttribute("src", "showColumn.do");
		cell.setAttribute("title", columnClass);
		
		recordColumnHide(theFunction, columnClass, true);
	}
	
	function showColumn(theFunction, columnClass, cell) {
		var panelUpLinks = $A(getElementsByClassName(columnClass));
					  panelUpLinks.each(function(panelUpLink) {
												 panelUpLink.style.display = 'inline';
												 });
		$(columnClass + "-header").style.display = 'inline';
		cell.innerHTML = "<img src='" + webContextPath + "/icons/hide-column.png' />";
		cell.setAttribute("src", 'hideColumn.do');
		cell.onclick=function() {
						hideColumn(columnClass, this); 
						return false;
		}; //onclick should be overridden by your javascript
		cell.setAttribute("title", columnClass);
		
		recordColumnHide(theFunction, columnClass, false);
	}
	
	function recordColumnHide(page, column, hidden) {
		now = new Date();
		var params = "page=" + page + "&column=" + column + "&hidden=" + hidden + "&time=" + now.getTime();
		var myAjax = new Ajax.Request(webContextPath + '/toggleColumnHide.do',	{
				method: 'post',
				parameters: params,
				onFailure: function(request) {
					window.alert("There was an error recording your column preference.");
				}
				});
	} 
	
	function setFocus(div) {
	if (div) {
		div.focus();
	}
	}

    function selectDeselectAllBulk(selections, check) {
        for (i = 0; i < selections.length; i++) {
            selections[i].checked = check;
        }
    }
    
    function isNumeric(text)
    {
        var validChars = "0123456789";
        var isNumber=true;
        var char;
     
        for (i = 0; i < text.length && isNumber == true; i++) { 
            char = text.charAt(i); 
            if (validChars.indexOf(char) == -1)
            {
                isNumber = false;
            }
        }
        return isNumber;
    }

    function escapeSpecialChar(text) {
        // Convert any smart entities - such as smart-quotes when text has been copied from Word or Outlook etc.
        text = text.replace( /\u2018/g, "'" );
        text = text.replace( /\u2019/g, "'" );
        text = text.replace( /\u201c/g, '"' );
        text = text.replace( /\u201d/g, '"' );
        text = text.replace( /\u2013/g, '-' );
        text = text.replace( /\u2014/g, '--' );

    	// Escape any special characters
    	text = escape(text);
    	return text;
    }