// JavaScript Document

/*
Instructions for use:

1) To make an input required, include class="reqd" and an id.

Example - text:
<input name="Name" type="text" size="50" maxlength="50" class="reqd" id="Name" value="<?php sticky_value('Name');?>"/>

Example - radio (don't forget the label around the option set!):
<label for="Claims3" id="Claims3">
<input name="Claims3" id="Claims30" type="radio" value="Yes" class="reqd" <?php sticky_radio("Claims3","Yes");?> />Yes
<input name="Claims3" id="Claims31" type="radio" value="No" class="reqd" <?php sticky_radio("Claims3","No");?> />No
</label>

2) To make an input box numeric only, include class="numOnly" and an id.  To specify minimum and maximum values, add class(es) "min=" and/or "max=".  To change zeros to blanks, add class "zeroisblank".

Example:
<input name="EmployeeCount" type="text" size="8" maxlength="8" class="numOnly zeroisblank min=0 max=100" id="EmployeeCount" value="<?php sticky_value('EmployeeCount');?>"/>

3) To validate an email address, include class="email" and an id.

Example:
<input name="Email" type="text" size="60" maxlength="80" class="email" id="email" value="<?php sticky_value('Email');?>"/>
	
4) To require that various fields be filled in if the user selects a specific radio button or fills in information in a particular field, and that the fields NOT be filled in if the user selects the radio button or fills in information in the field, include class="crossCheck" and a list of the associated field ids.	

Example:
<label for="Claims3" id="Claims3">
<input name="Claims3" id="Claims30" type="radio" value="Yes" class="reqd crossCheck Claiminfo anotherField" <?php sticky_radio("Claims3","Yes");?> />Yes
<input name="Claims3" id="Claims31" type="radio" value="No" class="reqd" <?php sticky_radio("Claims3","No");?> />No
</label>

5) To require that the sum of a set of entries equals 100, and to update the total when the user changes one of the entries, include class="equals100=myName" in each of the input fields, and include id="myNameLabel" in the total area.  If the group of entries should only be checked if a certain radio button is checked, then include class="equ100Active=radioID".

Example:
<table border="0" cellspacing="0" cellpadding="5">
<tr>
<th><label for="ClaimsAdjusting" id="ClaimsAdjusting">Do you do claims adjusting?</label></th>
<td>
<input name="ClaimsAdjusting" id="ClaimsAdjusting0" type="radio" value="Yes" tabindex="163"class="reqd showNewDiv crossCheck OutsideAdjusters InsideAdjusters" <?php sticky_radio("ClaimsAdjusting","Yes");?> /><label for="ClaimsAdjusting0">Yes</label>
<input name="ClaimsAdjusting" id="ClaimsAdjusting1" type="radio" value="No" tabindex="164" class="reqd hideNewDiv" <?php sticky_radio("ClaimsAdjusting","No", true);?> /><label for="ClaimsAdjusting1">No</label>
</td>
</tr>
</table>

<div class="pi_explainer" id="incomeAreasLabel">Total must equal 100%</div>
<input <?php create_text("AdjustIACasualty","1","3","187","numOnly min=0 max=100 equals100=incomeAreas equ100Active=ClaimsAdjusting0"); ?>/> % Casualty
<input <?php create_text("AdjustIAEnvironmentalLiability","1","3","188","numOnly min=0 max=100 equals100=incomeAreas equ100Active=ClaimsAdjusting0"); ?>/> % Environmental Liability
<input <?php create_text("AdjustIAInlandMarine","1","3","189","numOnly min=0 max=100 equals100=incomeAreas equ100Active=ClaimsAdjusting0"); ?>/> % Inland Marine

6)	To validate that the user agreed to the submission terms, make id of the 'Yes' radio button "Agreement0".
	Example:<td><input name="Agreement" id="Agreement0" type="radio" value="Yes" <?php sticky_radio("Agreement","Yes");?> />
            <label for="Agreement0">Yes</label>
            <input name="Agreement" id="Agreement1" type="radio" value="No" <?php sticky_radio("Agreement","No", true);?> />
            <label for="Agreement1">No<span class="explainer3">NOTE: This constitutes a digital signature.</span></label></td>

7.  Showing and Hiding Divs:

Checkboxes with class = 'showDiv' will show the div with the same id + '_sh' when they are checked and hide it when they're not checked.

Radio buttons with class = 'showDiv' will show the div with id = radioName + '_sh' when they are checked
Radio buttons with class = 'hideDiv' will hide the div with id = radioName + '_sh' when they are checked

Text input fields with class = 'showDiv' will show the div with the same id + '_sh' when they are not blank and hide it when they are blank.

All radio options inside the div should have a default value set.  The default radio should have class = 'default'.

All text inputs in the <div> will be deleted when the <div> is hidden, and all radio buttons in the <div> will reset to their defaults.

8.  Summation Fields:

Input fields with class = 'sumPercentsInto_summationId' will be summed into the element with id = 'summationId'.
The summation will end with '%'.

Input fields with class = 'sumDollarsInto__summationId' will be summed into the element with id = 'summationId'.
The summation will be formatted '$x,xxx'.
*/

//************************************************************************************************
var numCheckOK = true;
var emailCheckOK = true;
var processingAlert = false;

$(function() {
	// Initialize.
	$('input.showDiv').each(function(index) {
		showOrHideDiv(this);
  	});

	$("input:radio.hideDiv").each(function(index) {
		hideDivRadio(this);
	});
	
	$("input[class^='sumPercentsInto_'],input[class*=' sumPercentsInto_']").each(function(index) {
		updateTheSum(this, 'sumPercentsInto_');
	});
	
	$("input[class^='sumDollarsInto_'],input[class*=' sumDollarsInto_']").each(function(index) {
		updateTheSum(this, 'sumDollarsInto_');
	});
	
	// Event handlers
	$("input:text.showDiv").blur( function() {
		showOrHideDiv(this);
	});
	
	$("input.showDiv").click( function() {
		showOrHideDiv(this);
	});
	
	$("input:radio.hideDiv").click( function() {
		hideDivRadio(this);
	});
	
	$("input[class^='sumPercentsInto_'],input[class*=' sumPercentsInto_']").blur( function() {
		updateTheSum(this, 'sumPercentsInto_');
	});
	
	$("input[class^='sumDollarsInto_'],input[class*=' sumDollarsInto_']").blur( function() {
		updateTheSum(this, 'sumDollarsInto_');
	});
	
	$('.numOnly').blur( function() {
		numCheck(this);
	});
	
	$('.email').blur( function() {
		emailCheck(this);
	});
	
	$('.streetAddress').blur( function() {
		streetAddressCheck(this);
	});
	
	// Create "Help" icons
	$('span.qapp_question').append('<img src="../images/help.png" width="14" height="14" alt="Get Help" title="Get Help" longdesc="../images/help.gif" onclick="javascript: showHelp();" />');
										  
	$('span.qapp_question').click( function() {
		showHelp();
	});
	
	$('form').submit( function() {
		return validForm();				  
	});
	
	document.onkeydown = keyHit;
});

//************************************************************************************************
function numCheck(elem) {
	// Validate numeric fields where the class contains "numOnly", and optionally "min=" or "max=".
	numCheckOK = true;
	if (elem.className.indexOf("keepErrorColor") == -1) {
		markField(elem, "");
	}
	
	if (elem.value != "") {
		// isNAN does not recognize commas as value numeric data.  Remove commas from the value.
		var myValue = elem.value.replace(",","");
		
		if (isNaN(myValue)) { // Not a number
			numCheckOK = flagError(elem, "Only numbers are allowed in this field.");
		}
		else {
			myValue = parseFloat(myValue);
			var mySplitResult = elem.className.split(" ");
			
			for (var i=0; i<mySplitResult.length; i++) {
				if (mySplitResult[i].indexOf("min=") == 0) { // A minimum value was supplied
					var minVal = mySplitResult[i].substring(4,mySplitResult[i].length);
				}
				else if (mySplitResult[i].indexOf("max=") == 0) { // A maximum value was supplied
					var maxVal = mySplitResult[i].substring(4,mySplitResult[i].length);
				}
				else if ((mySplitResult[i].indexOf("zeroisblank") == 0) && (elem.value == 0)) { // Zero equals blank
					elem.value = "";
				}
			}
			if (myValue < minVal) {
				numCheckOK = flagError(elem, "Minimum value allowed = " + minVal + ".");
			}
			else if (myValue > maxVal) {
				numCheckOK = flagError(elem, "Maximum value allowed = " + maxVal + ".");
			}
		}
	}
	if (numCheckOK) {
		refreshTotal(elem);
	}
	return true;

	//************************************************************************************************
	function refreshTotal(thisTag) {
		// If this tag belongs to a group of tags that should total 100, calculate the total of the values 
		// of the tags and display it in the group label.
		if (thisTag.className.indexOf("equals100=") > -1) {
			// Get the id of the "total" label.
			var myClasses = thisTag.className.split(" ");
			for (i=0; i<myClasses.length; i++) {
				if (myClasses[i].indexOf("equals100") > -1) {
					var classID = myClasses[i];
					var labelID = strPart(classID, "equals100=") + "Label";
					i = myClasses.length;
				}
			}

			// Add up the values for this class.  (Must escape "=".)
			var total = 0;
			$('.equals100\\=' + classID.substr(10,classID.length - 10)).each(function(index) {
				if ($(this).val()) total += parseFloat($(this).val());							
			});
			$('#' + labelID).html("Total = " + Math.round(total * 100) / 100 + "% (must equal 100% to submit)");
		}
	}
}

//************************************************************************************************
function emailCheck(elem) {
	// Validate email fields where the class contains "email".
	emailCheckOK=true;
	if (elem.className.indexOf("keepErrorColor") == -1) {
		markField(elem, "");
	}

	var msgStr = "This email address is invalid.  Please enter a valid one.";
	var invalidChars = " /:,;";
	
	if (elem.value == "") {
		return true;
	}
	for (var i=0; i<invalidChars.length; i++) {
		var badChar = invalidChars.charAt(i);
		if (elem.value.indexOf(badChar) > -1) {
			emailCheckOK = flagError(elem, msgStr);
			return false;
		}
	}
	var atPos = elem.value.indexOf("@",1);
	if (atPos == -1) {
		emailCheckOK = flagError(elem, msgStr);
		return false;
	}
	if (elem.value.indexOf("@",atPos+1) != -1) {
		emailCheckOK = flagError(elem, msgStr);
		return false;
	}
	var periodPos = elem.value.indexOf(".",atPos);
	if (periodPos == -1) {
		emailCheckOK = flagError(elem, msgStr);
		return false;
	}
	if (periodPos + 3 > elem.value.length) {
		emailCheckOK = flagError(elem, msgStr);
		return false;
	}
	emailCheckOK=true;
	return true;
}

//************************************************************************************************
function streetAddressCheck(elem) {
	// Validate street address fields where the class contains "streetAddress".
	if (elem.className.indexOf("keepErrorColor") == -1) {
		markField(elem, "");
	}

	if (elem.value == "") {
		return true;
	}
	var b = 0 ;
	while( elem.value.charAt(b).match(/\s/) ) b++ ;
	if (isNaN(elem.value.charAt(b))) { // First non-blank character is not a number
		flagError(elem, "Street addresses must begin with a number. Please enter a valid address.");
		return false;
	}
}

//************************************************************************************************
function flagError(thisTag, errorMsg) {
	// Field error processing
	markField(thisTag, "invalid"); // Change background color to the error color.
	jqueryAlert(thisTag.id, "Invalid entry.", errorMsg);
	return false;
}

//************************************************************************************************
function validForm() {
	var allGood = true;

	if (!numCheckOK || !emailCheckOK) { // Don't do the form check if there was an error in the current field.
		return false;
	}
	
	// Remove all "keepErrorColor" and "invalid" classes.
	$('.keepErrorColor').each(function(index) {
		$(this).removeClass('keepErrorColor')
	});
	$('.invalid').each(function(index) {
		$(this).removeClass('invalid')
	});
	
	// Make sure all required fields are filled in and that an option is selected from each option group.
	var id;
	$('.reqd').each(function(index) {
		if (this.type == 'radio') {
			validEntry = false;
			$('[name=' + this.name + ']:checked').each(function() {
				validEntry = true;
			});
		} else if ($(this).val() == '') validEntry = false;
		else validEntry = true;
		
		if (!validEntry) {
			if (allGood) id = this.id;
			allGood = false;
			$(this).addClass('keepErrorColor');
			markField(this, "invalid");
		}
	});
	if (!allGood) {
		jqueryAlert(id, 'Required information is missing.', 'Please enter information in all the highlighted areas and then click the \'Submit\' button again.');
		return false;
	}

	// Make sure all equals100 fields add up to 100.
	var myList = "";
	$('.numOnly').each(function(index) {
		// This element has an "numOnly" class
		var skip = false;
		var myClass = "";
		var classList = $(this).attr('class').split(' ');
		$.each( classList, function(index, item){
			if (item.substr(0,13) == 'equ100Active=') {
				// This element has an "equ100Active=" class
				$('#' + item.substr(13, item.length - 13) + ':not(:checked)').each(function() {
					// The radio button associated with "equ100Active=" is not checked
					skip = true;
					return false;
				});
			} else if (item.substr(0,10) == 'equals100=') myClass = item;
		});
			
		if (myClass && !skip) {
			// Add the class to the list if it's not already in the list.
			if (myList.indexOf(myClass) == -1) myList += myClass + " ";
		}
	});
	
	if (myList != "") {
		myList = myList.substr(0, myList.length - 1); 
		myListArray = myList.split(' ');
		$.each( myListArray, function(index, item){
			allGood = totalEquals100(item);
			if (!allGood) return false;
		});
	}
	if (!allGood) return false;

	// Make sure all crossCheck fields are appropriately filled or empty.
	if (crossCheckFieldsOK() == false) return false;
	
	// Make sure the user has agreed to the submission conditions.
	$('#Agreement0:not(:checked)').each(function(index) {
		allGood = false;
		markField(this, "invalid"); // Change background color to the error color.
		jqueryAlert(this.id, "Do you accept the terms?", "You must check 'YES' to indicate that you accept the terms of this form submission.");
	});
	return allGood;

	//************************************************************************************************
	function totalEquals100(classStr) {
		var total = 0;
		var foundFirst = false;
		var id;
		
		// Add up the values for this class.  (Must escape "=".)
		$('.equals100\\=' + classStr.substr(10,classStr.length - 10)).each(function(index) {
			if ($(this).val()) total += parseFloat($(this).val());							
		});
		
		if (total == 100) return true;
		else {
			// Incorrect total for this class. Flag the bad fields.
			$('.equals100\\=' + classStr.substr(10,classStr.length - 10)).each(function(index) {
				$(this).addClass('keepErrorColor');
				markField(this, "invalid");
				if (!foundFirst) {
					foundFirst = true;
					id = this.id;
				}
			});
			
			jqueryAlert(id, 'The total does not equal 100%.', 'Current total = ' + total + '%.<br /><br />Please edit the highlighted entries so that the total equals 100%, and then click the \'Submit\' button again.');
			return false;
		}
	}

	//************************************************************************************************
	function crossCheckFieldsOK() {
		
		var validEntry = true;
		var errorMsg = "";
		var classList;
		
		// Find all the crosscheck fields.
		$('.crossCheck').each(function(index){
			if ((this.type != "radio" && this.type != "checkbox" && $(this).val()) || this.checked) {
				// All associated fields must be filled in.
				classList = $(this).attr('class').split(' ');
				$.each( classList, function(index, item){
					$('#' + item).each(function(index) {
						if ((this.type != "radio" && this.type != "checkbox" && !$(this).val()) || ((this.type == "radio" || this.type == "checkbox") && !this.checked)) { 
							// Found a matching tag that the user didn't fill in
							$(this).addClass('keepErrorColor');
							markField(this, "invalid");
							validEntry = false;
							errorMsg = "You have selected an option that requires that you enter additional information.<br \/><br \/>Please change the option or add the missing information in the highlighted fields and then click the 'Submit' button again.";
						}
					});
				});
			
			} else if ((this.type != "radio" && this.type != "checkbox" && !$(this).val()) || ((this.type == "radio" || this.type == "checkbox") && !this.checked)){
				// No associated fields must be filled in.
				classList = $(this).attr('class').split(' ');
				$.each( classList, function(index, item){
					$('#' + item).each(function(index) {
						if ((this.type != "radio" && this.type != "checkbox" && $(this).val()) || this.checked) { 
							// Found a matching tag that the user did fill in
							$(this).addClass('keepErrorColor');
							markField(this, "invalid");
							validEntry = false;
							errorMsg = "You have selected an option that requires that you leave certain fields blank.<br \/><br \/>Please change the option or delete the extra information from the highlighted fields and then click the 'Submit' button again.";
						}
					});
				});
				if (!validEntry) {
					// If this tag has an associated div that has been hidden, make it visible.
					$('#' + this.id + '.showDiv').each(function(index){
						if (this.type == 'radio') $('#' + this.name + '_sh').show(100);
						else $('#' + this.id + '_sh').show(100);
					});
				}
			}
			
			if (!validEntry) {
				$(this).addClass('keepErrorColor');
				markField(this, "invalid");
				jqueryAlert(this.id, 'You entered conflicting information.', errorMsg);
				return false;
			}
	   });
	   return validEntry;
	}
}

//************************************************************************************************
function keyHit(evt) {
/* If the user presses the Enter key, ignore it.  This is necessary because if the Enter key causes an automatic "Submit", and the information in the current field triggers the flagError routine, then there will be a conflict in the processing order between the field processing and the form processing. */

	var enterKey = 13;
	var thisKey;
	
	if (evt) thisKey = evt.which; // this works with some browsers
	else thisKey = window.event.keyCode; // this works with other browsers
	
	if (!processingAlert && (thisKey == enterKey)) return false; // Ignore the Enter key
	else return true; // Process all other keys
}

//************************************************************************************************
function markField(thisTag, newClass) {
	
	// If there's a label, mark it.
	var changedLabel = false;
	
	$('LABEL[for=' + thisTag.id + ']').each(function(index) {
		changedLabel = true;
		$(this).removeClass('invalid');
		if (newClass != '') $(this).addClass(newClass);
	});
	
	if (!changedLabel) { // There is no label for this input.
		$(thisTag).removeClass('invalid');
		if (newClass != '') $(thisTag).addClass(newClass);
	}
}

//************************************************************************************************
function strPart(fullStr, matchStr) {
	// Returns the portion of fullStr following the first occurrence of matchStr
	// and ending with the character before first space character or the end of the string.
	// Examples:
	// strPart("zz abc=xxx yy","abc=") = "xxx"
	// strPart("zz abc=xxx","abc=") = "xxx"
	// strPart("zz abc=xxx yy","mmm") = ""
	
	var myArr = fullStr.split(" ")
	for (var i=0; i<myArr.length; i++) {
		if (myArr[i].indexOf(matchStr) == 0) {
			return myArr[i].substring(matchStr.length, myArr[i].length);
		}
	}
	return "";
}

//************************************************************************************************
// This function formats numbers by adding commas
function numberFormat(nStr,prefix){
	var prefix = prefix || '';
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1))
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	return prefix + x1 + x2;
}	

//************************************************************************************************
function updateTheSum(e, theClass) {
	var classes = $(e).attr("className").split(" ");
		
	for (var i = 0; i < classes.length; i++){
		if ( classes[i].substr(0,theClass.length) == theClass ){
			// Get the id of the element where the sum should be displayed.
			summationID = classes[i].substr(theClass.length, classes[i].length - theClass.length);
			var theSum = 0;
			
			// Find all the inputs that contain the class and sum their values.
			$("input." + classes[i]).each(function(index) {
				if (!isNaN(parseInt($(this).val()))) theSum += parseInt($(this).val());		  
			});
			
			// Display the sum in the element with the required id.
			if (theClass == 'sumPercentsInto_') $("#" + summationID).text(theSum + "%");
				else $("#" + summationID).text(numberFormat(theSum, '$'));
		}
	}
}

//************************************************************************************************
function showOrHideDiv(e) {
	if (e.type == 'text') {
		var str = $(e).val().replace(/^\s+|\s+$/g, ''); // Trim whitespace.
		if (str == '') {
			if (hideTheDiv(e) == false) {
				// User canceled hiding the div.  Move the focus back to the original field.
				setTimeout(function () { $(e).focus() }, 50);
			}
		} else {
			$('#' + e.id + '_sh').show(100);
		}
	
	} else if ($(e).is(':checked')) { // Show div
		if(e.type == 'radio') $('#' + e.name + '_sh').show(100); // radio
			else $('#' + e.id + '_sh').show(100); // checkbox

	} else { // Hide div (checkbox only)
		if (hideTheDiv(e) == false) $(e).attr('checked', true);
	}
}

//************************************************************************************************
function hideDivRadio(e) {
	if ($(e).is(':checked')) { // Hide div
		hideTheDiv(e);
	}
}

//************************************************************************************************
function hideTheDiv(e) {
	
	var askForConfirmation = false;
	
	if(e.type == 'radio') var baseId = e.name; // radio
		else var baseId = e.id; // checkbox
	
	// Are any child values set? (text input or textarea)
	$('#' + baseId + '_sh input:text,#' + baseId + '_sh textarea').each(function(index) {
		if ($(this).val() != '') askForConfirmation = true;			 
	});
	
	// Any child values set? (non-default radio buttons)
	$('#' + baseId + '_sh input:radio.default').each(function(index) {
		if (!$(this).is(':checked')) askForConfirmation = true;			 
	});
	
	if (!askForConfirmation) {
		doIt();
		return true;
	
	} else {
		// Must first destroy the dialog functionality completely before re-creating it so the we can reset the options.
		// Use autoOpen since we will only be using the dialog once.
		processingAlert = true;
		playAlertSound();
		$('#alert').dialog('destroy');
		var $alert = $('#alert') 
			.html('Are you sure you want to select this option?<br \/><br \/>Selecting this option will delete related information that you have entered.')
			.dialog({
				autoOpen: true,
				modal: true,
				buttons: {
					'Yes': function() {
						processingAlert = false;
						$(this).dialog('close');
						doIt();
						return true;
					},
					'No': function() {
						processingAlert = false;
						$(this).dialog('close');
						if (e.type == 'text') {
							// Move the focus back to the original field.
							setTimeout(function () { $(e).focus() }, 50);
						} else if (e.type == 'radio') {
							// Reset the radio button.
							$('input[name=' + e.name + ']:radio.showDiv').attr('checked', true);
						} else if (e.type == 'checkbox') {
							// Reset the checkbox
							$(e).attr('checked', true);
						}
						return false;
					}
				},
				title: 'Please confirm.',
			});
	}
	
	function doIt() {
		// Set all text input fields or textareas in the div to blank.
		$('#' + baseId + '_sh input:text,#' + baseId + '_sh textarea').each(function(index) {
			$(this).val('');		 
		});
		// Set all radios buttons in the div to the default.
		$('#' + baseId + '_sh input:radio.default').each(function(index) {
			$(this).attr('checked', true);	 
		});
		
		// Hide all child divs (recursive).
		$('#' + baseId + '_sh input.showDiv').each(function(index) {
			showOrHideDiv(this);
		});
	
		$('#' + baseId + '_sh input:radio.hideDiv').each(function(index) {
			hideDivRadio(this);
		});			
		
		// Hide the div itself.
		$('#' + baseId + '_sh').hide(100);
		return true;
	}
}

//************************************************************************************************
function showHelp() {
	if (document.URL.indexOf("qapp_Alarms") >= 0) person = "Bill West";
	else if (document.URL.indexOf("qapp_Bonds") >= 0) person = "Karen Metcalf";
	else if (document.URL.indexOf("qapp_CommercialAuto") >= 0) person = "Karen Metcalf";
	else if (document.URL.indexOf("qapp_Homeowners") >= 0) person = "Karen Metcalf";
	else if (document.URL.indexOf("qapp_PI") >= 0) person = "Bill West";
	else if (document.URL.indexOf("qapp_Restaurant") >= 0) person = "Michelle Nowell";
	else if (document.URL.indexOf("qapp_Security_Guards") >= 0) person = "Bill West";
	else if (document.URL.indexOf("qapp_SmallBusiness") >= 0) person = "Michelle Nowell";
	else if (document.URL.indexOf("qapp_WorkerComp") >= 0) person = "Karen Metcalf";
	
	jqueryAlert("", "We're here to help!", "If you have any questions about filling out this form, please call:<br /><br />(800) 843-8550 or 760-471-7116<br />between 8:30AM and 4:30PM Pacific Time<br /><br />and ask to speak with " + person + ".");
}

//************************************************************************************************
function jqueryAlert(id, msgTitle, msgStr) {
	
	processingAlert = true; // This makes the Enter key active.
	playAlertSound();
	
	// Set the focus on the unhidden input or textarea before the <hr /> or <h3> before the offending field.
	if (id != '') {
		var saved = false;
		var done = false;
		var temp;
		$('h3:not(:hidden), hr:not(:hidden), input:not(:hidden), textarea:not(:hidden)').each(function(index) {
			if (!done) {
				if (this.id == id) {
					if (!saved) saved = this;
					$(saved).focus();
					done = true;
				} else if ((this.nodeName == 'H3') || (this.nodeName == 'HR')) {
					saved = temp;
				} else {
					temp = this;
					if (!saved) saved = this;
				}
			}
		});
	}
	
	// Must first destroy the dialog functionality completely before re-creating it so the we can reset the options.
	// Use autoOpen since we will only be using the dialog once.
	$('#alert').dialog('destroy');
	var $alert = $('#alert') 
		.html(msgStr)
		.dialog({
			autoOpen: true,
			modal: true,
			closeOnEscape: true,
			buttons: { "OK": function() { $(this).dialog("close"); } },
			title: msgTitle,
			close: function(event, ui) { 
				if (id != '') $('#' + id).focus(); // Set the focus again since the modal nature of the dialog messes up the focus
				processingAlert = false;
			} 
		});
}

//************************************************************************************************
function playAlertSound() {
	// Removed this because it can generate various error / confirmation messages in browsers.  Darn!
//	$('#sound').remove();
//	$('body').append('<embed id="sound" hidden="true" autostart="true" type="audio/x-wav" src="../javascript/Windows_Ding.wav" >');
}