// =============== 
// ! WINDOW LOAD   
// =============== 
$j(window).load(function(){
	
	
	$j('.elementRow, .pageControls').addClass('autoclear');
	
	//convert widths to em's
	$j('.elementColumn,.targetForm').each(function(i){
		var baseSize = $j('body').css('font-size').replace(/px/,'');
		var w = $j(this).width();
		$j(this).width( w/baseSize + "em");
	});
	
	// in the case of a form, warn the user before leaving
	warnBeforeUnload = false;
	window.onbeforeunload = function(){ 
		if ( warnBeforeUnload && warnBeforeUnloadCount > 0 ) {
			return "If you leave this form now, all your data will be lost.";
		}
	}
	
	// if this is not a direct view
	if ( formPluginRequestMode != "direct" ) {
		
		// in the case of multi-page forms, try to use the browser history
		$j.history(function( e, ui ){
			
			// if there is a hash
			if ( ui.value != "" ) {
			
				// get the formID and page number from this hash
				var hashArray = ui.value.split("_");
				var formID = hashArray[0] + "_" + hashArray[1];
				var pageNum = (hashArray[2]-1);
				
				var parentForm = $j("#" + formID);
				var currentFormPage = $j(parentForm).data( "currentFormPage" );
				
				// if the form is not already on this page
				if ( currentFormPage != pageNum ) {
					
					// move to that page and update the form settings and hash
					var formPages = $j(parentForm).find(".formPage");
					$j(formPages).eq( currentFormPage ).hide();	
					$j(formPages).eq( pageNum ).show();
					
					// we may need to remove the next page control and turn on the submit button
					if ( (pageNum+1) == $j(parentForm).data("formPages") ) {
						$j(parentForm).find(".nextPage").hide();
						$j(parentForm).find(".submitBtn").show();
						$j(parentForm).find(".userConfirmation").show();
					} else {
						$j(parentForm).find(".nextPage").show();
						$j(parentForm).find(".submitBtn").hide();
						$j(parentForm).find(".userConfirmation").hide();
					}
					
					$j(parentForm).find(".prevPage").show();
					
					// update the current page
					$j(parentForm).data( "currentFormPage", pageNum );
					
					// refresh our page counter
					$j(parentForm).find(".pageBreak .pagenum").text( "Page " + (pageNum+1) + " of " + $j(parentForm).data("formPages") );
		
					window.scrollTo(0,0); //need to test this in IE
				
				}
			
			// if there is not a hash, every form should be on its first page
			} else {
				
				$j("form.cf_form").each( function() {
				
					var currentFormPage = $j(this).data( "currentFormPage" );
					var totalPages = $j(this).data("formPages");
					var formPages = $j(this).find(".formPage");
					
					// if its a one page form, we can leave it alone
					if ( totalPages > 1 ) {
						$j(formPages).eq( currentFormPage ).hide();	
						$j(formPages).eq( 0 ).show();
						$j(this).data( "currentFormPage", 0 );
						$j(this).find(".prevPage").hide();
						$j(this).find(".nextPage").show();
						$j(this).find(".submitBtn").hide();
						$j(this).find(".pageBreak .pagenum").text( "Page 1 of " + $j(this).data("formPages") );
						window.scrollTo(0,0);
					}
				
				} );
				
			}
			
		});

	}
	
	$j('.toolTipHover .elementContainer').hover(function(){
		$j(this).find('.toolTip').css('display','block');
	},
	function(){
		$j(this).find('.toolTip').css('display','none');
	});
	
	
	$j('body').append('<div id="formAlerts"></div>');
	$j('#formAlerts').dialog({
		modal:true,
		autoOpen:false,
		resizable:true
	});
	
	/*
		cfform auto creates an onSubmit handler, so we remove it
	*/
	$j("form.cf_form").removeAttr("onSubmit");
	
	
	// we configure our inputs for validation
	$j(".formPage").fsValidator();
	$j(".userConfirmation").fsValidator();
	
	// =================== 
	// ! SUBMIT THE FORM   
	// =================== 
	$j("input.submitBtn").click( function() {

		var thisForm = $j(this).parents("form:first");
		var cmdField = thisForm.find(".cmd_cf_forms");
		var failed = 1;
		
		// before we validate, we need to prep the user confirmation email address field
		if( $j(thisForm).find('.userConfirmationEmail').val() == 'my email address' ){
			$j(thisForm).find('.userConfirmationEmail').val('');
		}
		
		// validate the form
		$j(thisForm).find(".formPage").fsValidateElements( {
			onFail: function(data){ failed = failAction( data ); },
			onPass: function(data){ passAction( data ); }
		} );
		
		// if we passed form validation, we need to pass confirmation email validation, too
		if (failed == 0){
			$j("#" + thisForm.fixAttr("id") + " .userConfirmation").fsValidateElements( {
				onFail: function(data){ failed = simpleFailAction( data ); },
				onPass: function(data){ simplePassAction( data ); }
			} );
		}
		
		// if we pass validation, we submit the form
		if (failed == 0){
			
			warnBeforeUnload = false;
			
			//make sure we've calculated all total fields
			$j('input.showTotals,input.thisFormMonetaryTotal').each(function(i,e){
				setMonetaryTotal(e);
			});
			
			// any disabled form fields need to be "un-disabled" as some browsers won't include their values in the submission
			$j(thisForm).find(":input:disabled").removeAttr( "disabled" );
			
			// we should, however, disable our submit button and save for later
			$j(this).prop('disabled', true).val( "please wait..." );
			$j('input.saveForLater').prop('disabled', true);
			
			// we need to collect a list of hidden unused/undisplayed conditional children
			var hiddenElements = [];
			$j(thisForm).find("div.hiddenElem").each( function() {
				
				hiddenElements.push( $j(this).fixAttr("id").replace( "elementContainer_", "" ) );
				
			} );
			$j(thisForm).find("input.hiddenElements").val( hiddenElements.toString() );
			
			// we need to collect a list of hidden unused/undisplayed conditional children
			var selectedLabels = [];
			$j(thisForm).find("input:checkbox:checked, input:radio:checked").each( function() {
				
				var elemObj = {};
				
				elemObj.label = "unBool:"+ $j.trim( $j(this).parent().text() );
				elemObj.value = "unBool:"+ $j.trim( $j(this).val() );
				elemObj.id = $j(this).fixAttr("name").replace( "el_", "");
				
				selectedLabels.push( elemObj );
				
			} );
			$j(thisForm).find('select option:selected').each(function(){
			
				var elemObj ={};
				
				elemObj.label = "unBool:"+ $j.trim($j(this).text() );
				elemObj.value = "unBool:"+ $j.trim($j(this).val() );
				elemObj.id = $j(this).parent().fixAttr("name").replace( "el_", "");
				
				selectedLabels.push(elemObj);
			
			});
			
			// if our form has been "framed" we need to record this
			var isFramed = ( ( formPluginRequestMode == "direct" ) && ( top.location != location ) );
			
			$j(thisForm).append( '<input type="hidden" name="isFramed" value="' + isFramed + '">' )
			
			$j(thisForm).find("input.selectedLabels").val( $j.jSONToString(selectedLabels) );

			// validate human submission
			validateHumanity( thisForm.fixAttr("id") );
			
			$j(cmdField).val( "submitForm" );
			thisForm.submit();
		}		
		
	});
	
	$j('.userConfirmationToggle').click(function() {
		if($j(this).prop('checked')){
			$j(this).parents("div.userConfirmation").find('.userConfirmationEmail').removeAttr('disabled');
		}else{
			$j(this).parents("div.userConfirmation").find('.userConfirmationEmail').attr('disabled','disabled');
		}
	});
	
	//send user confirmation
	$j('.userConfirmationEmail').focus(function(){
		if( $j(this).val() == 'my email address' ){
			$j(this).val('');
		}
	}).blur(function(){
		if($j(this).val() == ''){
			$j(this).val('my email address');
		}
	});
	
	// this function updates the save for later email input to match the most recently enetered email address from the form (if there is one)
	$j(".saveForLater").click( function() {
		
		var parentElem = $j(this).parents(".saveForLaterPanel");
		var parentForm = $j(this).parents("form:first");
		var emailTarget = $j(parentElem).find(".sflEmail");
		
		// get the last email form field value that is not empty
		var emailDefault = $j(parentForm).find(":input[class*='email'][name!='sflEmail']:last").val();
		$j(parentElem).find('.saveForLaterEmail').slideDown();
		$j(emailTarget).val( emailDefault );
	});
	
	$j('.sflCancel').click(function() {
		$j(this).parents().find('.saveForLaterEmail').slideUp();
	});
	
	// establish validation on our save for later panels
	$j(".saveForLaterPanel").fsValidator();

	// submit types
	$j(".sflBtn").click( function() {
		
		var thisForm = $j(this).parents("form:first");
		var cmdField = thisForm.find(".cmd_cf_forms");
		var formID = $j(thisForm).fixAttr("id");
		
		// validate our save for later panel
		$j(thisForm).find(".saveForLaterPanel").fsValidateElements( {
			onFail: function(data) { 
				if (simpleFailAction( data ) == 0) {
					// any disabled form fields need to be "un-disabled" as some browsers won't include their values in the submission
					$j(thisForm).find(":input:disabled").removeAttr( "disabled" );
					$j(cmdField).val( "saveForLater" );
					validateHumanity(formID);
					thisForm.submit();
				}
			},
			onPass: function(data){ 
				//Make sure we don't display the warning message when we attempt to leave the form
				window.onbeforeunload=null;
				simplePassAction( data ); 
			}
		} );
		
	});
	
	
	// treat the enter key as if it is a tab key
	$j('form.disableEnter input').live("keypress", function(e) {
	    /* ENTER PRESSED*/
	    if (e.keyCode == 13) {
	        /* FOCUS ELEMENT */
	        var inputs = $j(this).parents("form").eq(0).find("div.formPage").find(":input:enabled");
	        var idx = inputs.index(this);
	
	        // if we are on the last enabled input in the form
	        if (idx == inputs.length - 1) {
	            inputs[0].select()
	        } else {
	            inputs[idx + 1].focus(); //  handles submit buttons
	            inputs[idx + 1].select();
	        }
	        return false;
	    }
	});	
	
	
	// =================== 
	// ! FORM PAGINATION   
	// =================== 

	// grab all forms which were generated using the forms module
	var formCount = $j("form.cf_form");
	
	// apply the double-click workaround to radio buttons for deselecting them (aka the "soda machine" response) - do not include currency fields (they're handled elsewhere)
	$j(formCount).find(":radio").not("input.moneyBtn").dblclick( function() {
		$j(this).removeAttr( "checked" );
	} );
	
	// we'll loop over them to assign pagination data to the forms
	$j(formCount).each( function() {
	
		// what page are we on?
		$j(this).data( "currentFormPage", 0 );
		// how many pages does the form have?
		$j(this).data( "formPages", $j(this).find(".formPage").length );
		
		// display the first page
		$j(this).find(".formPage").eq( 0 ).show();
		
		// if there are multiple pages, set the pagination controls
		if ( $j(this).data("formPages") > 1 ) {
			$j(this).find(".nextPage").show();
			$j(this).find(".pageBreak .pagenum").text("Page 1 of " + $j(this).data("formPages"));
			
			// clicking next page needs to invoke validation
			$j(this).find(".nextPage").click( function() {

				var parentForm = $j(this).parents("form.cf_form");
				var currentFormPage = $j(parentForm).data("currentFormPage");
				var formPages = $j(parentForm).find(".formPage");
				
				// run validation
				$j(formPages).eq( currentFormPage ).fsValidateElements( {
					// these are our callback functions
					onFail: function(data){ failed = failAction( data ); },
					onPass: function(data){	passAction( data ); }
				});
	
				// if we pass validation, we move to the next page
				if(failed == 0){
					var nextFormPage = (currentFormPage + 1);
					
					$j(formPages).eq( currentFormPage ).hide();	
					$j(formPages).eq( nextFormPage ).show();
					
					// update the url hash
					window.location.hash = $j(parentForm).fixAttr("id") + "_" + (nextFormPage+1);
					
					$j(parentForm).data( "currentFormPage", nextFormPage );
					
					// turn on the previous control
					$j(parentForm).find(".prevPage").show();
					
					// we may need to remove the next page control and turn on the submit button
					if ( (nextFormPage+1) == $j(parentForm).data("formPages") ) {
						$j(parentForm).find(".nextPage").hide();
						$j(parentForm).find(".submitBtn").show();
						$j(parentForm).find(".userConfirmation").show();
					}
					
					// refresh our page counter
					$j(parentForm).find(".pageBreak .pagenum").text( "Page " + (nextFormPage+1) + " of " + $j(parentForm).data("formPages") );
					
					// if this is page two or later, we will wanr on reload
					if ( nextFormPage >= 1 ) {
						warnBeforeUnload = true;
					}
	
					window.scrollTo(0,0); //need to test this in IE
				}		
	
			});
			
			// clicking the previous page simply moves backward
			$j(this).find(".prevPage").click( function() {

				var parentForm = $j(this).parents("form.cf_form");
				var currentFormPage = $j(parentForm).data("currentFormPage");
				var formPages = $j(parentForm).find(".formPage");

				var prevFormPage = currentFormPage-1;
				
				$j(formPages).eq( currentFormPage ).hide();	
				$j(formPages).eq( prevFormPage ).show();
				
				$j(parentForm).data( "currentFormPage", prevFormPage );
					
				$j(parentForm).find(".nextPage").show();
				$j(parentForm).find(".submitBtn").hide();
				$j(parentForm).find(".userConfirmation").hide();
				
				if ( (prevFormPage) == 0 ) {
					$j(parentForm).find(".prevPage").hide();
					window.location.hash = "";
				} else {
					window.location.hash = $j(parentForm).fixAttr("id") + "_" + (prevFormPage+1);
				}
	
				$j(parentForm).find(".pageBreak .pagenum").text( "Page " + (prevFormPage+1) + " of " + $j(parentForm).data("formPages") );

				window.scrollTo(0,0);
	
			});	
			
		}else{ //only one page
			$j(this).find(".submitBtn").show();
			$j(this).find(".userConfirmation").show();
		}
		
		// find any radio buttons which are set as "none" options
		$j(this).find(":radio.radioNone").each( function() {
			
			var parentForm = $j(this).parents("form.cf_form");
			var radioArrayName = $j(this).fixAttr("name");

			// if this radio button array does not already have something selected
			if ( $j(parentForm).find(":radio[name='" + radioArrayName + "']:checked").length == 0 ) {
				// select this
				$j(this).attr( "checked", "checked" );
			}
			
		} );
		
	});
	
	
	// ===================== 
	// ! MONETARY HANDLING   
	// ===================== 

	// create a monetaryTotal field if we need one
	if ( $j(":input[class*='monetary'], input.moneyBtn").length > 0 ) {
		$j(".hydraulics").after( '<input type="hidden" name="monetaryTotal" class="thisFormMonetaryTotal" size="20" value="0.00">' );
	}
	// any time the money field is updated, the total field is updated too
	$j(":input[class*='monetary']").change( function() {
		
		setMonetaryTotal( $j(this) );

	} );
	// formatting
	//get the formID from the hidden field
	var formID = $j("input[type='hidden'][name='formID']").val();
	var monetaryDefault = '0';
	
	if($j('#form_'+formID).data('formOptions').monetaryDefault == 'blank'){
		monetaryDefault = '';
	}
	
	//Check if the Payment option to remove decimal formatting from monetary fields is enabled
	if($j('#form_'+formID).data('formOptions').monetaryDecimal == 'whole'){
		//Apply standard monetary formatting, but with no thousanth seperator and without any decimal places
		$j("input:text[class*='monetary']").autoNumeric({aSep: '', mDec: 0, aNeg: '-'});
	
	//If decimal formatting is not being removed
	}else{
		//Apply standard monetary formatting, but with no thousanth seperator
		$j("input:text[class*='monetary']").autoNumeric({aSep: '', aNeg: '-'});
	}
	
	
	
	// any time a monetary radio or checkbox is clicked, update totals
	$j("input.moneyBtn").live( "click", function() {
	
		setMonetaryTotal( $j(this) );
	
	} );
	// double-click on radio button, too
	$j("input.moneyBtn:radio").live( "dblclick", function() {
		$j(this).removeAttr( "checked" );
		setMonetaryTotal( $j(this) );
	} );
	
	// disable any monetary total fields
	$j("input.showTotals").attr( "disabled", "disabled" );
	
	// prepare our totals (if needed)
	$j("form.cf_form").each( function() {
		if ( $j(this).find( ":input[class*='monetary'], input.moneyBtn:checked" ).length > 0 ) {
			setMonetaryTotal( $j(this).find("input")[0] );
		}
	} );
	
	
	// ======================== 
	// ! ENFORCE FORM OPTIONS   
	// ======================== 
	$j(".cf_form").each( function() {
		
		// get the options for this form
		var formOptions = $j(this).data( "formOptions" );
		
		// set our tool tip position
		switch( formOptions.defaultTipPosition ) {
			case "above" : $j(this).find(".targetForm").addClass('toolTipRight'); break;
			case "mouseover" : $j(this).find(".targetForm").addClass('toolTipHover'); break;
			default : break;		
		}
		
		// and our label positions
		if ( formOptions.defaultLabelPosition == "left" ) { 
			$j(this).find(".targetForm").addClass('labelLeft');
		} else { 
			$j(this).find(".targetForm").removeClass('labelLeft'); 
		}
		
	} );
	
	
	// ============================================= 
	// ! ADD A CLEAR BUTTON TO A FILE UPLOAD INPUT   
	// ============================================= 
	$j(":file").live( "click", function() {
		
		// if we do not yet have a clear control
		if ( $j(this).parent().find( "span.clearFile" ).length == 0 ) {
			
			$j(this).after( ' <span class="linkLike clearFile">clear</span>' );
		
		}
		
	} );
	
	
	// ====================== 
	// ! CLEAR A FILE INPUT   
	// ====================== 
	$j(".clearFile").live( "click", function() {
		
		// get the current html for this element (the html does not include any selected file)
		var thisHTML = $j(this).parent().html();
		// remove the clear control
		$j(this).remove();
		
		// overwrite the element
		$j(this).parent().html( thisHTML );
		
	} );
	
	
	// ===========================================================
	// ! DECODE THE HTML-ENCODED SYMBOLS IN VALUE OF TEXT FIELDS
	// ===========================================================
	//Added by A.Wack 7/28/11 to solve BUG-9081
	$j('.elementBody input[type="text"]').each(function(){
	
		//Loops through each text field and replaces HTML-number-encoded apostophes, backslashes and quotes with the character's symbol.
		$j(this).val($j(this).val().replace(/&#39;/g, "\'").replace(/&#92;/g,"\\").replace(/&#34;/g,'"'));
	
	});
	

}); 
// =================== 
// ! END WINDOW LOAD   
// =================== 

	
	
// =========================== 
// ! RETOTAL MONETARY FIELDS   
// =========================== 
function setMonetaryTotal( elem ) {

	// set the total
	var totalVal = 0.00;
	
	// get the parent form
	var parentForm = $j(elem).parents("form:first");
	
	// find all monetary fields in the parent form which are not inside a "hidden" conditional question
	var monetaryFields = $j( parentForm ).find( ".elementContainer" ).not( ".hiddenElem" ).find( ":input[class*='monetary'], input.moneyBtn:checked" );
	
	// sum the values
	totalVal = $j(monetaryFields).sumValues().toFixed(2);
	
	// if we are not allowing less than zero
	if ( $j(parentForm).data("formOptions").zeroMinimum == 1 || isNaN( $j(parentForm).data("formOptions").zeroMinimum ) ) {
		// update our value
		totalVal = Math.max( totalVal, 0 ).toFixed(2);
	}

	
	$j( parentForm ).find( ".thisFormMonetaryTotal" ).val( totalVal );
	$j( parentForm ).find("input.showTotals").val( totalVal );
	$j( parentForm ).find("div.showTotals").text( totalVal );
}



// ============================ 
// ! FAILED VALIDATION ACTION   
// ============================ 
function failAction( resultObj ) {
	
	var failed = 0;
	
	// here we could loop over our failed elements and assign a change handler to them, 
	// so they are each validated individually as the user attempts to correct the error
	for (var elementID in resultObj) {
		
		failed++;
		
		$j("#" + elementID).change( function() {
			$j(this).parent().fsValidateElements( {
				onFail: function(data){ failAction( data ); },
				onPass: function(data){ passAction( data ); }
			} );
		});
		// and we could also display our error message / tip for each element
		// as an example, we just color the bg of their containers
		$j("#" + elementID).parents(".elementContainer").addClass('valFail');

		$j("#" + elementID).parents(".elementContainer").find('.valFailMsg').remove(); //clear any old fail messages
		$j("#" + elementID).parents(".elementContainer").append('<p class="valFailMsg"></p>');
		for (var i=0; i < resultObj[elementID].length; i++) {
			$j("#" + elementID).parents(".elementContainer").find('.valFailMsg').append(resultObj[elementID][i] + '<br>');
		}

	}
	
	// if there were errors
	if ( failed > 0 ) {
		// scroll to our first failed element
		$j(window).scrollTo( $j( ".elementContainer.valFail:first" ), 1200 );
	}
	
	return failed;
	
}



// =========================== 
// ! ALTERNATE FAILED ACTION   
// =========================== 
function simpleFailAction ( resultObj ) {
	
	var failed = 0;
	
	for (var elementID in resultObj) {
		failed++;
		$j("#" + elementID).change( function() {
			$j(this).parent().fsValidateElements( {
				onFail: function(data){ simpleFailAction( data ); },
				onPass: function(data){ simplePassAction( data ); }
			} );
		});

		$j("#" + elementID).next('.valFailMsg').remove(); //clear any old fail messages
		$j("#" + elementID).after('<p class="valFailMsg"></p>');
		for (var i=0; i < resultObj[elementID].length; i++) {
			$j("#" + elementID).next('.valFailMsg').append(resultObj[elementID][i] + '<br>');
		}
	}
	
	return failed;

}


// ========================== 
// ! PASS VALIDATION ACTION   
// ========================== 
function passAction( resultObj ) {
	
	for (var elementID in resultObj) {
		// here we could remove each error message / tip for each element if the element passes
		$j("#" + elementID).parents(".elementContainer").removeClass('valFail');
		$j("#" + elementID).parents(".elementContainer").find('.valFailMsg').remove(); //clear any old fail messages
	}
}


// ========================= 
// ! ALTERNATE PASS ACTION   
// ========================= 
function simplePassAction( resultObj ) {
	
	for (var elementID in resultObj) {
		$j("#" + elementID).next('.valFailMsg').remove(); //clear any old fail messages
	}
}



// ============================================= 
// ! initiate our conditional elements on load   
// ============================================= 
function setConditionalElement( childElem, parentElem, reponseValuesJSON, brokenLink ) {
	
	var reponseValues = $j.toJSON( reponseValuesJSON.replace( /unBool:/g, "" ) );
	
	// ================================================== 
	// ! CUSTOM CHECKBOX / RADIO EVENT: "testCondition"   
	// ================================================== 
	$j(parentElem).find(":checkbox, :radio").bind( "testCondition", function() {
		
		var displayChild = false;
		var childIsHidden = $j(childElem).hasClass( "hiddenElem" );
		
		// if this is not a hidden parent (hidden parents should always cascade their hidden display to conditional children)
		if ( !$j(parentElem).hasClass( "hiddenElem" ) ) {
			var selectedElems = $j(parentElem).find(":checked");
			
			$j(selectedElems).each( function() {
				
				// if this item's value is in the array of response values
				if ( $j.inArray( $j(this).val().replace( /'/g, "&#39;" ).replace( /\\\\/g, "&#92;" ).replace( /\\"/g, "&#34;" ), reponseValues ) != -1 ) {
					displayChild = true;
				}
				
				// if this value was not found and can be resolved to a numeric value
				if ( !displayChild && !isNaN( $j(this).val()*1 ) ) {
					
					// get the value
					var thisVal = $j(this).val()*1;
					
					// create a decimal version
					var thisDecimal = thisVal.toFixed(2);
					
					// try again as an integer
					if ( $j.inArray( thisVal.toString(), reponseValues ) != -1 ) {
						displayChild = true;
					// or as a decimal string (could be a dollar value)
					} else if ( $j.inArray( thisDecimal.toString(), reponseValues ) != -1 ) {
						displayChild = true;
					}
				}
				
			} );
		}
		
		// if we need to display the child AND it is currently hidden
		if ( displayChild && childIsHidden ) {
			$j(childElem).removeClass( "hiddenElem" );
			// we refresh the input names so CF will recognize the response
			$j(childElem).find(":input").each( function() {
				$j(this).attr( "name", $j(this).fixAttr("name").replace( "_disabled", "" ) );
			} );
			// and remove the disabled hidden field
			$j(childElem).find(".disabledPlaceHolder").remove();
			// and we display it
			$j(childElem).parent().show();
			
			// if the child element is a monetary field
			if ( $j(childElem).find( ":input[class*='monetary'], input.moneyBtn:checked" ).length > 0 ) {
				setMonetaryTotal( $j(this) );
			}
			
		} else if ( !displayChild && !childIsHidden ) {
			$j(childElem).addClass( "hiddenElem" );
			$j(childElem).find(":input").each( function() {
				// if this is not already disabled, disable it now
				if ( $j(this).fixAttr( "name" ).indexOf( "_disabled" ) < 0 ) {
					$j(this).attr( "name", $j(this).fixAttr("name") + "_disabled" );
				}
			} );
			// inject a hidden field with the disabled name
			$j(childElem).find(".disabledPlaceHolder").remove();
			$j(childElem).append( '<input type="hidden" class="disabledPlaceHolder" name="el_' + $j(childElem).fixAttr("id").replace( "elementContainer_", "" ) + '_disabled">' );
			
			$j(childElem).parent().hide();
			
			if ( $j(childElem).find( ":input[class*='monetary'], input.moneyBtn:checked" ).length > 0 ) {
				setMonetaryTotal( $j(this) );
			}
			
		}
		
		// if this child is itself a parent run the trigger on this child, as well
		if ( $j(childElem).hasClass( "conditionalParent" ) ) {
			$j(childElem).find(":checkbox, :radio").trigger( "testCondition" );
			$j(childElem).find("select").trigger( "testCondition" );
		}
		
	} );
	// make sure that custom event is triggered by the click event
	$j(parentElem).find(":checkbox, :radio").click( function() {
		$j(this).trigger( "testCondition" );
	} );
	
	
	// ============================================= 
	// ! CUSTOM SELECT MENU EVENT: "testCondition"   
	// ============================================= 
	$j(parentElem).find("select").bind( "testCondition", function() {
		
		var displayChild = false;
		var isPleaseSelect = false;
		
		if ( !$j(parentElem).hasClass( "hiddenElem" ) ) {
			isPleaseSelect = ( $j(this).find(":selected").text().substr(0,13) == "Please Select" );
			
			// if this value is among the conditional response triggers AND is not a please select option
			if ( !isPleaseSelect && $j.inArray( $j(this).val(), reponseValues ) != -1 ) {
				displayChild = true;
			}
			
			// if this value was not found and can be resolved to a numeric value
			if ( !isPleaseSelect && !displayChild && !isNaN( $j(this).val()*1 ) ) {
				
				// get the value
				var thisVal = $j(this).val()*1;
				
				// create a decimal version
				var thisDecimal = thisVal.toFixed(2);
				
				// try again as an integer
				if ( $j.inArray( thisVal.toString(), reponseValues ) != -1 ) {
					displayChild = true;
				// or as a decimal string (could be a dollar value)
				} else if ( $j.inArray( thisDecimal.toString(), reponseValues ) != -1 ) {
					displayChild = true;
				}
			}
		}
			
		if ( displayChild ) {
			$j(childElem).removeClass( "hiddenElem" );
			$j(childElem).find(":input").each( function() {
				$j(this).attr( "name", $j(this).fixAttr("name").replace( "_disabled", "" ) );
			} );
			$j(childElem).parent().show();
			
			if ( $j(childElem).find( ":input[class*='monetary'], input.moneyBtn:checked" ).length > 0 ) {
				setMonetaryTotal( $j(this) );
			}
			
		} else {
			$j(childElem).addClass( "hiddenElem" );
			$j(childElem).find(":input").each( function() {
				// if this is not already disabled, disable it now
				if ( $j(this).fixAttr( "name" ).indexOf( "_disabled" ) < 0 ) {
					$j(this).attr( "name", $j(this).fixAttr("name") + "_disabled" );
				}
			} );
			$j(childElem).parent().hide();
			
			if ( $j(childElem).find( ":input[class*='monetary'], input.moneyBtn:checked" ).length > 0 ) {
				setMonetaryTotal( $j(this) );
			}
			
		}
		
		if ( $j(childElem).hasClass( "conditionalParent" ) ) {
			$j(childElem).find(":checkbox, :radio").trigger( "testCondition" );
			$j(childElem).find("select").trigger( "testCondition" );
		}
	} );
	$j(parentElem).find("select").change( function() {
		$j(this).trigger( "testCondition" );
	} );
	
	// assign a parent class to the parent
	$j(parentElem).addClass( "conditionalParent" );
	
	// call the custom event to pre-configure the proper conditional state
	$j(parentElem).find(":checkbox, :radio").trigger( "testCondition" );
	$j(parentElem).find("select").trigger( "testCondition" );

}
// ======================================================= 
// ! VALIDATE THAT A HUMAN BEING IS SUBMITTING THIS FORM   
// ======================================================= 
function validateHumanity( formID ) {
	
	var validatorIndexes = [];
	var validationStr = "";
	var validationEnd = "left";
	
	var thisForm = $j( "#" + formID );
	
	// get all the form elements for this form
	var formElems = $j( thisForm ).find( ".elementContainer :input" ).not('input:checkbox:not(:checked), input:radio:not(:checked), [name*="disabled"], [type="file"]' );
	
	// get the indexes of any two of the elements
	validatorIndexes.push( Math.floor( Math.random() * formElems.length ) );
	validatorIndexes.push( Math.floor( Math.random() * formElems.length ) );
	
	// loop over the array
	$j(validatorIndexes).each( function() {
		
		// get the corresponding element
		var thisElem = $j(formElems).eq(this);
		
		// determine what type of element this is
		var thisType = thisElem[0].type;
		var thisName = thisElem[0].name;
		var thisValue = "";
		
		switch( thisType ) {
			// if this is a radio or checkbox (multi-inputs, some unselected)
			case "radio":
			case "checkbox":
			  
				var checkedInputArray = $j(thisElem).parents(".elementContainer").find(":checked");
				
				// if there are more than 1 checked checkboxes
				if ( checkedInputArray.length > 1 ) {
					//loop through all the checked checkboxes, and their value to the list, and add a comma ensure this is a proper list
					thisElem.parents(".elementContainer").find(":checked").each(function(){
						thisValue = thisValue + $j(this).val()+ ',';
					});
					
					//remove the trailing comma, as the last element in the list won't have one
					thisValue = thisValue.left(thisValue.length - 1);
				// if there is only 1 checked box then we add a space instead of a comma to eliminate the yes = true coldfusion conversion
				}else if(checkedInputArray.length == 1){
					thisValue = thisElem.parents(".elementContainer").find(":checked").val() + ' ';
				}
			  
				break;
			// otherwise it only has a single value to pick from
			default:
				thisValue = $j(thisElem).val();
				break;
		}
		// append to our string
		if ( validationEnd == "left" ) {
			validationStr = validationStr + thisName + ":" + $j.trim( thisValue ).left(10) + " |";
		} else {
			validationStr = validationStr + thisName + ":" + $j.trim( thisValue ).right(10) + " ";
		}
		
		validationEnd = "right";
	} );
	
	// encode our validation string into the form
	validationStr = $j.base64Encode( validationStr );
	$j(thisForm).find(":input[name='hydraulics']").val( validationStr );
}


// =================================================== 
// ! GET THE LEFT NUMBER OF CHARACTERS FROM A STRING   
// =================================================== 
String.prototype.left = function(n) {
    return this.substring(0, n);
}


// ==================================================== 
// ! GET THE RIGHT NUMBER OF CHARACTERS FROM A STRING   
// ==================================================== 
String.prototype.right = function(n) {
    
    var thisStart = this.length-n;
    
    if ( thisStart >= 0 ) {
    	return this.substring(thisStart);
    } else {
    	return this.substring(0);
    }
}


// ============================== 
// ! AUTO NUMBER QUIZ QUESTIONS   
// ============================== 
function numberQuestions( formID ) {
	
	// we only do this when the form type is a quiz
	if ( isQuiz ) {
		
		var i = 1;
		var formObj = $j(formID);
		var qArray = $j(formObj).find("div.elementContainer").has('label');
		
		// remove all existing numbering
		$j("span.autoNumber").remove();
		
		// loop over our questions array
		$j(qArray).each( function() {
			
			// find the question text and prepend the question number
			$j(this).find("div.groupLabel, label").eq(0).prepend( '<span class="autoNumber">' + (i++) + '. </span>' );
		} );
	}
}


// =========================================================================== 
// ! HELP JQUERY 1.6.x HANDLE NON-EXISTING ATTRIBUTES IN THE ATTR() FUNCTION   
// =========================================================================== 
jQuery.fn.fixAttr = function(attr) {
	
	// test to see if the attr exists
	var needAttr = ( $j(this).attr( attr ) === undefined );
	var returnVal = "";
	
	// if it does not exist, create an empty one
	if ( needAttr ) {
		
		returnVal = getUniqueName(8);
		$j(this).attr( attr, returnVal );
	
	// otherwise return the one it has
	} else {
		returnVal = $j(this).attr( attr );
	}
	
	return returnVal;
	
}


