/***************************************************************************************************/
function Validator(/*string*/elementName,/*string*/labelName,/*string*/errorMessage){
	this.elementName=elementName;
	this.labelName=labelName;
	this.errorMessage=errorMessage;
	this.elementToValidate=null;
	this.labelToChange=null;
	this.formObject=null;
}

Validator.prototype.constructor=Validator;

/*methods of Validator*/
Validator.prototype.init=function (/*DOM Element*/formObject){
	this.elementToValidate=formObject[this.elementName];
	//console.debug(this.elementName+' '+this.labelName);
	//console.debug(this.elementToValidate);
	this.labelToChange=document.getElementById(this.labelName);
	this.formObject=formObject;
}

/***************************************************************************************************/
function RequiredFieldValidator(/*string*/elementName,/*string*/labelName,/*string*/errorMessage){
	Validator.prototype.constructor.call(this,elementName,labelName,errorMessage);
	this.genericError = "* Required field - must be filled in.";
}

/*
 * Extending the Validator class
 */

RequiredFieldValidator.prototype = new Validator();
RequiredFieldValidator.prototype.constructor = RequiredFieldValidator;

/*
 * Function the provides the validation
 */
RequiredFieldValidator.prototype.validate=function(){
	// if its a text box
	if("text" == this.elementToValidate.type || "textarea" == this.elementToValidate.type || "hidden" == this.elementToValidate.type){
		var value = trim (this.elementToValidate.value);
		if(0 < value.length)
			return true;
		return false;
	}

	// console.dir(this.elementToValidate);

	// if its a dropdown
	if("select-one" == this.elementToValidate.type || "select-multiple" == this.elementToValidate.type){
		for(var i=0; i< this.elementToValidate.options.length; i++) {
			if(this.elementToValidate.options[i].selected && this.elementToValidate.options[i].value != "")
				return true;
		}
		return false;
	}

	// if its a radio or checkbox type is not defined for it but for its elements
	var element = (this.elementToValidate.length)?this.elementToValidate[0]:null;

	// console.dir(elementToValidate);

	if(element && ("radio" == element.type || "checkbox" == element.type)){
		for(var i=0; i< this.elementToValidate.length; i++)
			if(this.elementToValidate[i].checked)
				return true;
		return false;
	}

	return false;
}


/***************************************************************************************************/

function PatternValidator(/*string*/elementName,/*string*/labelName,/*string*/patternString,/*string*/errorMessage){
	Validator.prototype.constructor.call(this,elementName,labelName,errorMessage);
	this.genericError = "Questions in <span class='midredbold'>RED</span> don't meet specified format";
	this.patternString=patternString;
}

/*
 * Extending the Validator class
 */

PatternValidator.prototype = new Validator;
PatternValidator.prototype.constructor = PatternValidator;
/*
 * Function the provides the validation
 */
PatternValidator.prototype.validate=function(){
	// if there is no value to check don't check it

	var valueStr = trim(this.elementToValidate.value);

	if(0 == valueStr.length)
		return true;

	var result = valueStr.match(this.patternString);
	if (result){
		return true;
	}

	return false;
}

/***************************************************************************************************/

function SelectionValidator(/*string*/elementName,/*string*/labelName,/*string*/patternString,/*string*/errorMessage){
	Validator.prototype.constructor.call(this,elementName,labelName,errorMessage);
	this.genericError = "Questions in <span class='midredbold'>RED</span> don't have number of required answers selected";
	this.patternString=patternString;
}

/*
 * Extending the Validator class
 */

SelectionValidator.prototype = new Validator;
SelectionValidator.prototype.constructor = SelectionValidator;
/*
 * Function the provides the validation
 */
SelectionValidator.prototype.validate=function(){

	var str = "";
	var selectedCount = 0;
	for(var i=0; i< this.elementToValidate.length; i++){
		if(this.elementToValidate[i].checked){
			str+="1";
			selectedCount++;
		}
	}
	// if there is no value selected don't check it
	if (str=="" || selectedCount==0){
		return true;
	}

	var isFullRegularExpression = (this.patternString.indexOf('^')!=-1) && (this.patternString.indexOf('$')!=-1);

	var result = null;

	// convert it to string
	selectedCount += '';

	if (isFullRegularExpression){
		result = selectedCount.match(this.patternString);
	}else{
		result = selectedCount.match("^["+this.patternString+"]$");
	}

	if (result){
		return true;
	}
	return false;
}

/***************************************************************************************************/

function SelectionTextBoxValidator(/*string*/elementName,/*string*/labelName,
								   /*string*/groupName,/*string*/selectedValue,/*string*/errorMessage){

	Validator.prototype.constructor.call(this,elementName,labelName,errorMessage);
	this.genericError = "Values in <span class='midredbold'>RED</span> are required when option is selected";
	this.groupName=groupName;
	this.group=null;
	this.selectedValue=selectedValue;
}

/*
 * Extending the Validator class
 */

SelectionTextBoxValidator.prototype = new Validator;
SelectionTextBoxValidator.prototype.constructor = SelectionTextBoxValidator;

SelectionTextBoxValidator.prototype.init=function (/*DOM Element*/formObject){
	Validator.prototype.init.call(this,formObject);
	this.group=formObject[this.groupName];

}

/*
 * Function the provides the validation
 */
SelectionTextBoxValidator.prototype.validate=function(){
	if (!this.elementToValidate){
		return true;
	}

	var strValue = trim(this.elementToValidate.value);

	if (strValue.length>0){
		return true;
	}
	for(var i=0; i< this.group.length; i++){
		if(this.group[i].checked && (this.group[i].value==this.selectedValue) )
			return false;
	}
	return true;
}


/***************************************************************************************************/

function FunctionValidator(/*string*/elementName,/*string*/labelName,/*function*/func,/*string*/errorMessage){
	Validator.prototype.constructor.call(this,elementName,labelName,errorMessage);
	this.genericError = "";
	this.func=func;

}

/*
 * Extending the Validator class
 */

FunctionValidator.prototype = new Validator;
FunctionValidator.prototype.constructor=FunctionValidator;


/*
 * Function the provides the validation
 */
FunctionValidator.prototype.validate=function(){
	//console.debug("about to call the function");
	return eval(this.func)(this.elementToValidate,this.formObject);

}

/***************************************************************************************************/

// for Form validations
// the FormValidator Class does the basic validation

function FormValidator(/*boolean*/showSpecificMessageForRequiredFields,/*string*/errorClass,/*string*/normalClass){
	this.showSpecificMessageForRequiredFields = false || showSpecificMessageForRequiredFields;
	this.errorClass = errorClass || "";
	this.normalClass=normalClass||"";
	this.summaryHolder=null;
	this.formObject=null;
	this.validators=new Array();
	this.formName=null;
}

/*methods of FormValidator*/
// call this once the page is rendered with formName and summary id
FormValidator.prototype.init=function(/*string*/formName,/*string*/summaryLabel){
	this.formObject = document.forms[formName];
	this.formName=formName;
	this.summaryHolder =  document.getElementById(summaryLabel);
	// initialize all the validators too
	for (var i =0; i<this.validators.length;i++){
		this.validators[i].init(this.formObject);
	}

	// This validation is added specific to ProductForm to fix QC1351
	//if(this.formName == "ProductForm_product_form" ){
	//	var cont = document.getElementById('div_Connection_OS_Problem');
	//		cont.style.display = 'none';
	//}
}

// used to add validator to FormValidator
FormValidator.prototype.addValidator=function(/*Validator*/validator){
	if (validator instanceof Validator){
		this.validators.push(validator);
	}
}

FormValidator.prototype.validate=function(){

	var requiredFieldMissing = false;
	var otherErrorMessages = new Array();
	var requiredFieldErrorMessages = new Array();
	var errorFound= false;
	// first make sure all required fields are filled
	// whether to show one error message for all required fields
	// or more specific ones as determined by "showSpecificMessageForRequiredFields"
	// console.debug(this.validators.length);
	for (var i =0; i<this.validators.length;i++){
		var validator = this.validators[i];
		var validation = validator.validate();
		// console.debug("Running validation for "+validator.elementName+"="+validation);
		if (!validation){
			errorFound=true;
			if (validator.constructor == RequiredFieldValidator){
				requiredFieldMissing = true;
				if (!this.showSpecificMessageForRequiredFields
						&& requiredFieldErrorMessages.length==0){
					requiredFieldErrorMessages.push(validator.genericError);
				}else if (this.showSpecificMessageForRequiredFields){
					requiredFieldErrorMessages.push((validator.errorMessage!="")?validator.errorMessage:validator.genericError);
				}
				validator.labelToChange.className=this.errorClass;
			}else if (!requiredFieldMissing){
				otherErrorMessages.push((validator.errorMessage!="")?validator.errorMessage:validator.genericError);
				validator.labelToChange.className=this.errorClass;
			}
		}

	}

	var messages="";

	if (errorFound){
		if (requiredFieldMissing){
			for (var i =0; i<requiredFieldErrorMessages.length;i++){
				messages+=requiredFieldErrorMessages[i]+"<br>"
			}
		}else{
			// should not display same error messages???
			var displayedMessages = new Array();
			mainLoop:
			for (var i =0; i<otherErrorMessages.length;i++){
				for (var j=0; j<displayedMessages.length; j++){
					if (otherErrorMessages[i]==displayedMessages[j])
						continue mainLoop;
				}
				messages+=otherErrorMessages[i]+"<br>"
				displayedMessages.push(otherErrorMessages[i]);
			}
		}

		this.summaryHolder.innerHTML="<span class=\"normal\">" + messages + "</span>";
	}

	return !errorFound;

}

FormValidator.prototype.reset=function(){
		this.summaryHolder.innerHTML="";
		for (var i =0; i<this.validators.length;i++){
			var validator = this.validators[i];
			validator.labelToChange.className=this.normalClass;
		}
}

FormValidator.prototype.executeBeforeSubmitFunction=function(){
	try{
		if ("function"===typeof(_beforeSubmit)){
			var beforeSubmitFunction = _beforeSubmit;
			var result = new Object();
			result.proceed=null;
			eval (beforeSubmitFunction)(this.formObject, result);
			if (result.proceed===null){
				return true;
			}
			return result.proceed;
		}

	}catch(e){}
	return true;
}

FormValidator.prototype.submitForm=function(){
	this.formObject.submit();
}




/***************************************************************************************************/



function DateDropDown(/*string*/groupName){
	/* the hidden elemnts holding values */
	this.monthElement=null;
	this.dayElement=null;
	this.yearElement=null;
	/* name of the hidden elements holding values */
	this.monthElementName=null;
	this.dayElementName=null;
	this.yearElementName=null;
	/* the list elements holding the whole list*/
	this.dayElementList=null;
	this.yearElementList=null;
	/* group name to identify this group*/
	this.groupName=groupName;
	/* year range that will be created*/
	this.yearRange=null;
}

DateDropDown.prototype.constructor=DateDropDown;

DateDropDown.prototype.init=function (/*DOM Element*/formObject){

	if (this.monthElementName){
		this.monthElement=formObject[this.monthElementName];
		this.monthElement.value="";
	}

	if (this.dayElementName){
		this.dayElement=formObject[this.dayElementName];
		this.dayElement.value="";
		this.dayElementList=document.getElementById(this.dayElementName+"_list");
	}

	if (this.yearElementName){
		this.yearElement=formObject[this.yearElementName];
		this.yearElement.value="";
		this.yearElementList=document.getElementById(this.yearElementName+"_list");
		var fromYear = 0;
		var toYear = 0;
		// console.debug(this.yearRange);
		if (this.yearRange){
			var currentYear = new Date().getFullYear();
			var yearRange = new String(" "+this.yearRange+" ");
			// we have a range
			if (yearRange.indexOf(',')>=0){
				var rangeElements = yearRange.split(',');
				fromYear = trim(rangeElements[0]);
				fromYear = fromYear==""?currentYear:fromYear;
				toYear = trim(rangeElements[1]);
				toYear = toYear==""?currentYear:toYear;
			// we need to add to current year
			}else if (yearRange.indexOf('+')>=0){
				var difference = trim(yearRange)*1;
				fromYear = currentYear;
				toYear = difference+currentYear;
			// we need to subtract from current year
			}else if (yearRange.indexOf('-')>=0){
				var difference = trim(yearRange)*1;
				fromYear = difference+currentYear;
				toYear =currentYear;
			}
		}

		var desendingOrder = ((currentYear-fromYear) > (toYear - currentYear));
		if (desendingOrder){
			var temp = fromYear;
			fromYear = toYear;
			toYear=temp;
		}

		// populate the year drop down dynamically using the range
		for (var i = fromYear;((desendingOrder)?(i>=toYear):(i<=toYear));){
			this.yearElement.options[this.yearElement.length] = new Option(i, i);
			i = (desendingOrder)?i-1:i+1;
		}
	}
}

DateDropDown.prototype.isLeapYear=function(){
	var year = this.yearElement.value;
	if (year != '' && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {
		return true;
	}
	return false;
}

DateDropDown.prototype.changeMonth=function(){
	var selectedMonth =this.monthElement.value;

	var fromDay = 1;
	var toDay = 30;

	if (selectedMonth == '02') {
		toDay=29;
	}

	if (selectedMonth == '01' || selectedMonth == '03' ||
		selectedMonth == '05' || selectedMonth == '07' ||
		selectedMonth == '08' || selectedMonth == '10' ||
		selectedMonth == '12') {
		toDay=31;
	}

	this.addDays(fromDay,toDay,(this.dayElement.value>toDay));
	return true;
}

DateDropDown.prototype.changeYear=function() {
	if (this.monthElement.value == '02') {
		if (this.isLeapYear()) {
			 this.addDays(1,29,false);
		}else{
			this.addDays(1,28, (this.dayElement.value>28));
		}
	}
	return true;
}

DateDropDown.prototype.addDays=function(fromDay, toDay, /*boolean*/resetDays){
	var selectedValue = this.dayElement.value;

	for (i = this.dayElement.length - 1; i >= 1; i--) {
		this.dayElement.remove(i);
	}

	for (i = fromDay; i <= toDay; i++) {
		var str = new String(i);
		if (str.length == 1) {
			str = 0 + str;
		}
		this.dayElement.options[this.dayElement.length] =
			new Option(str, str, false, str == selectedValue);
	}
}

/***************************************************************************************************/


function DateDropDownsHolder(){
	this.dropDowns = new Array();
	this.formObject = null;
}

DateDropDownsHolder.prototype.constructor=DateDropDownsHolder;

DateDropDownsHolder.prototype.init= function (/*string*/formName){
	this.formObject = document.forms[formName];
	for (var i =0; i<this.dropDowns.length;i++){
		this.dropDowns[i].init(this.formObject);
	}
}

DateDropDownsHolder.prototype.addMonth=function (/*string*/groupName,/*string*/monthElementName){
	var dropDown = this.getDropDown(groupName);
	dropDown.monthElementName = monthElementName;
}

DateDropDownsHolder.prototype.addDay=function (/*string*/groupName,/*string*/dayElementName){
	var dropDown = this.getDropDown(groupName);
	dropDown.dayElementName = dayElementName;
}

DateDropDownsHolder.prototype.addYear=function (/*string*/groupName,/*string*/yearElementName,/*string*/yearRange){
	var dropDown = this.getDropDown(groupName);
	dropDown.yearElementName = yearElementName;
	dropDown.yearRange = yearRange;
}

DateDropDownsHolder.prototype.monthChanged=function (/*string*/groupName){
	var dropDown = this.getDropDown(groupName);
	return dropDown.changeMonth();
}

DateDropDownsHolder.prototype.yearChanged=function (/*string*/groupName){
	var dropDown = this.getDropDown(groupName);
	return dropDown.changeYear();
}


DateDropDownsHolder.prototype.getDropDown=function (/*string*/ groupName){
	for (var i =0; i<this.dropDowns.length;i++){
		if (this.dropDowns[i].groupName==groupName){
			return this.dropDowns[i];
		}
	}

	var dropDown = new DateDropDown (groupName);
	this.dropDowns.push(dropDown);
	return dropDown;

}

/***************************************************************************************************/

function ProductDropDownsHolder(){
	this.dropDowns = new Array();
	this.formObject = null;
}
ProductDropDownsHolder.prototype.constructor=ProductDropDownsHolder;

ProductDropDownsHolder.prototype.addChildDropDown=function (/*string*/ dropDownName, /*string*/ selectedProductElementName){
	var dropDown = new ProductDropDown(dropDownName,selectedProductElementName);
	this.dropDowns.push(dropDown);
}

ProductDropDownsHolder.prototype.init= function (/*string*/formName, /*string*/ nodeCid){
	this.formObject = document.forms[formName];
	for (var i =0; i<this.dropDowns.length;i++){
		this.dropDowns[i].init(this.formObject);
	}

	if (this.dropDowns[0]){
		getProductsForDropDown(nodeCid,this.dropDowns[0]);
	}	
}

ProductDropDownsHolder.prototype.dropDownChanged= function (/*string*/dropDownName, /*string*/selectedNodeCid, /*string*/selectedNodeName){
	var changedValueforDropDown = this.getDropDown(dropDownName);
	var childDropDownIndex = this.getChildDropDownIndex(dropDownName);

	if (changedValueforDropDown.selectedProductElementName) {
		dojo.byId(changedValueforDropDown.selectedProductElementName).value = changedValueforDropDown.dropDownListElement.options[changedValueforDropDown.dropDownListElement.options.selectedIndex].text;
	}

	// the first child will load data the rest should get disabled
	if (childDropDownIndex>0) {
		var count = 0;
		for (var i =childDropDownIndex; i<this.dropDowns.length;i++){
			this.dropDowns[i].dropDownListElement.disabled = true;
			if (count==0){
				getProductsForDropDown(selectedNodeCid,this.dropDowns[i]);
			} else {
				for (j = this.dropDowns[i].dropDownListElement.length - 1; j >= 1; j--) {
					this.dropDowns[i].dropDownListElement.remove(j);
				}
			}
			count++;
		}
	}
}

ProductDropDownsHolder.prototype.getDropDown=function (/*string*/ dropDownName){
	for (var i =0; i<this.dropDowns.length;i++){
		if (this.dropDowns[i].dropDownName==dropDownName){
			return this.dropDowns[i];
		}
	}
}

ProductDropDownsHolder.prototype.getChildDropDownIndex=function (/*string*/ dropDownName){
	for (var i =0; i<this.dropDowns.length;i++){
		if (this.dropDowns[i].dropDownName==dropDownName){
			if (this.dropDowns[i+1]){
				return (i+1);
			}
		}
	}
	return -1;
}



/***************************************************************************************************/

function ProductDropDown(/*string*/ dropDownName, /*string*/ selectedProductElementName){
	this.dropDownName=dropDownName;
	this.selectedProductElement=null;
	this.selectedProductElementName=selectedProductElementName;
	this.dropDownListElement=null;
}

ProductDropDown.prototype.constructor=ProductDropDown;

ProductDropDown.prototype.init=function (/*DOM Element*/formObject){
	if (this.selectedProductElementName){
		this.selectedProductElement=formObject[this.selectedProductElementName];
		this.selectedProductElement.value="";
	}
	this.dropDownListElement=document.getElementById(this.dropDownName);
	this.dropDownListElement.disabled = true;
}

ProductDropDown.prototype.changeValue=function(/*string*/selectedNodeCid, /*string*/selectedNodeName){
	setJsDropdownValue(this.dropDownName,selectedNodeCid,selectedNodeName);
	if (this.selectedProductElement){
		this.selectedProductElement.value=selectedNodeName;
	}
}

ProductDropDown.prototype.enableDropDown=function(){
	this.changeDropDownImageClass(false);
}

ProductDropDown.prototype.disableDropDown=function(){
	setJsDropdownDefaultValue(this.dropDownName,"","Select");
	this.changeDropDownImageClass(true);
}

ProductDropDown.prototype.changeDropDownImageClass=function(/*boolean*/ flag){
	var dropDownArrowElement= dojo.query("#"+this.dropDownName+"_DropdownContainer tr td.js_dropdown_btn a");
	if (dropDownArrowElement){
		dropDownArrowElement.toggleClass("hidden",flag);
	}
}

ProductDropDown.prototype.populateList=function(responseObject){
	if (responseObject==null ||  responseObject instanceof Error){
		console.debug("Error while getting list ");
		return;
	}

	// remove child nodes
	for (i = this.dropDownListElement.length - 1; i >= 1; i--) {
		this.dropDownListElement.remove(i);
	}

	for (var x in responseObject) {
		var jsonObject = responseObject[x];
		this.dropDownListElement.options[this.dropDownListElement.length] =
			new Option(jsonObject.nodeName, jsonObject.nodeCid);
	}

	var onChangeString = "productDropDowns.dropDownChanged('"+this.dropDownName+"',document.getElementById('"+this.dropDownListElement.id+"').value)";
	this.dropDownListElement.onchange = new Function(onChangeString);
	this.dropDownListElement.disabled = false;
}

/***************************************************************************************************/

function getProductsForDropDown(/*string*/ nodeCid, /*ProductDropDown*/ productDropDown){
	// console.debug("Making ajax call for "+nodeCid);
	dojo.xhrGet( {
		url: "/cusa/productListing.action?nodeCid="+nodeCid,
		handleAs: "json",
		load: function(responseObject, ioArgs) {productDropDown.populateList(responseObject);}

	});
	}




/***************************************************************************************************/
function trim (str) {
	if (str){
		str=str.replace(/\n+/g," ");
		str=str.replace(/^\s+|\s+$|\v|\r|\f/g,"");
		return str;
	}
	return "";
}

/***************************************************************************************************/

function moveToErrors(anchorName){
	var anchorToMoveTo = document.getElementById(anchorName)||document.anchors[anchorName];
	var moveToY = 0;
	if (anchorToMoveTo){
		if (anchorToMoveTo.posY){
			moveToY=anchorToMoveTo.posY;
		}else{
			moveToY=findPosYOfErrorDiv(anchorToMoveTo);
			anchorToMoveTo.posY=moveToY;
		}
	}
	window.scrollTo(0,moveToY);
}

function findPosYOfErrorDiv(obj) {
	var curtop = 0;
	if(obj.offsetParent)
		while(1){
			curtop += obj.offsetTop;
			if(!obj.offsetParent)
				break;
			obj = obj.offsetParent;
		}
	else if(obj.y)
		curtop += obj.y;
	return curtop;
}

/*******************************************************************************************************/
/* QC1368
 * by q04000, 06/10/2011
 * Need to declare these dojo libs in your jsp: dojo ; dojox.jsonPath.query ; dojo.string
 */
function ZipRelatedDropDown(/*string*/groupName){
	/* name of the hidden elements holding values */
	this.stateSelElementName=null;
	this.stateTxtElementName=null;
	this.countySelElementName=null;
	this.countyTxtElementName=null;
	this.citySelElementName=null;
	this.cityTxtElementName=null;

	/* the list elements holding the whole list*/
	this.stateSelElementCtrl=null;
	this.stateTxtElementCtrl=null;
	this.countySelElementCtrl=null;
	this.countyTxtElementCtrl=null;
	this.citySelElementCtrl=null;
	this.cityTxtElementCtrl=null;

	/* group name to identify this group*/
	this.groupName=groupName;

	/* zipcode */
	this.zipCode = null;

	/* json string contains all the TaxMaster records for a zipcode */
	this.jsonTaxRecords = null;

	/* year range that will be created*/
	this.yearRange=null;
}

ZipRelatedDropDown.prototype.constructor=ZipRelatedDropDown;

ZipRelatedDropDown.prototype.init=function (/*DOM Element*/formObject){
	if (this.stateSelElementName){
		this.stateSelElementCtrl=formObject[this.stateSelElementName];
		this.stateSelElementCtrl.value="";
	}
	if (this.stateTxtElementName){
		this.stateTxtElementCtrl=formObject[this.stateTxtElementName];
		this.stateTxtElementCtrl.value="";
	}

	if (this.countySelElementName){
		this.countySelElementCtrl=formObject[this.countySelElementName];
		this.countySelElementCtrl.value="";
	}
	if (this.countyTxtElementName){
		this.countyTxtElementCtrl=formObject[this.countyTxtElementName];
		this.countyTxtElementCtrl.value="";
	}

	if (this.citySelElementName){
		this.citySelElementCtrl=formObject[this.citySelElementName];
		this.citySelElementCtrl.value="";
	}
	if (this.cityTxtElementName){
		this.cityTxtElementCtrl=formObject[this.cityTxtElementName];
		this.cityTxtElementCtrl.value="";
	}
}

ZipRelatedDropDown.SELECT_ELEMENT = "SELECT";

ZipRelatedDropDown.prototype.populateList=function(dropDownCtrl, elementArray){
	// remove child nodes
	for (i = dropDownCtrl.length - 1; i > 0; i--) {
		dropDownCtrl.remove(i);
	}

	if( dropDownCtrl.length == 0 ){
		 dropDownCtrl.options[dropDownCtrl.length] = new Option(ZipRelatedDropDown.SELECT_ELEMENT, ZipRelatedDropDown.SELECT_ELEMENT);
	}

	for (var x in elementArray) {
		var strElement = elementArray[x];

		dropDownCtrl.options[dropDownCtrl.length] =
			new Option(strElement, strElement);
	}
}

//-------------


function ZipRelatedDropDownsHolder(needCounty, taxRateElementName){
	this.needCounty = needCounty;

	this.dropDowns = new Array();
	this.formObject = null;
	this.jsonZipRecords = null;
	this.zipCode = null;

	this.GROUP_NAME_STATE = "STATE";
	this.GROUP_NAME_COUNTY = "COUNTY";
	this.GROUP_NAME_CITY = "CITY";

	this.currentState = "";
	this.currentCounty = "";
	if( taxRateElementName ){
		this.taxRateElementName = taxRateElementName;
	} else {
		this.taxRateElementName = "";
	}
}

ZipRelatedDropDownsHolder.prototype.constructor=ZipRelatedDropDownsHolder;

ZipRelatedDropDownsHolder.prototype.init= function (/*string*/formName){
	this.formObject = document.forms[formName];
	for (var i =0; i<this.dropDowns.length;i++){
		this.dropDowns[i].init(this.formObject);
	}
}

ZipRelatedDropDownsHolder.prototype.setJsonZipRecords= function (/*string*/ zipCode, /*json string*/jsonZipRecords){
	this.zipCode = zipCode;
	this.jsonZipRecords = jsonZipRecords;
}

ZipRelatedDropDownsHolder.prototype.showStates = function ( zipCode ){
	results = retrieveDropdownArray( this.jsonZipRecords );

	if (results==null ||  results instanceof Error){
		console.debug("Error while getting state list ");
		this.showControl( "STATE", "NONE" );
		this.stateChanged( "" );
		return false;
	} else if( results.length < 1 ){
		this.showControl( "STATE", "NONE" );
		this.stateChanged( "" );

		return false;
	} else if(  results.length == 1 ) {
		//show textbox
		dropDown = this.getDropDown(this.GROUP_NAME_STATE);
		txtCtrl = dropDown.stateTxtElementCtrl;
		txtCtrl.value = results[0];
		this.showControl( "STATE", "TEXT" );

		this.stateChanged( results[0] );
	} else {
		//show dropdown
		dropDown = this.getDropDown(this.GROUP_NAME_STATE);
		dropDown.populateList( dropDown.stateSelElementCtrl, results );

		this.showControl( "STATE", "DROPDOWN" );

		this.stateChanged(dropDown.stateSelElementCtrl.value);
	}

	return true;
}

ZipRelatedDropDownsHolder.prototype.stateChanged = function ( state ){
	if( state == ZipRelatedDropDown.SELECT_ELEMENT ){
		this.currentState = "";
		results = null;
	} else {
   		this.currentState = state;
   		if( dojo.string.trim(state) == "" ){
   			results = null;
   		} else {
			results = retrieveDropdownArray( this.jsonZipRecords, state, this.needCounty );
		}
	}

	var dropDown, txtCtrl;

	//set the state value to state textbox although it's hidden
	//so that struts action and java code can always get the state value from
	//textbox, not from dropdown
	dropDown = this.getDropDown(this.GROUP_NAME_STATE);
	dropDown.stateTxtElementCtrl.value = this.currentState;

	if (results==null ||  results instanceof Error){
		if( this.needCounty ){
			//change county
			this.showControl( "COUNTY", "NONE" );
			this.countyChanged( "" );
		} else {
			//change city
			this.showControl( "CITY", "NONE" );
			this.cityChanged( "" );
		}
		return false;
	} else if( results.length < 1 ){
		if( this.needCounty ){
			//change county
			this.showControl( "COUNTY", "NONE" );
			this.countyChanged( "" );
		} else {
			//change city
			this.showControl( "CITY", "NONE" );
			this.cityChanged( "" );
		}
		return false;
	} else if(  results.length == 1 ) {
		//show textbox
		if( this.needCounty ){
			//change county
			dropDown = this.getDropDown(this.GROUP_NAME_COUNTY);
			txtCtrl = dropDown.countyTxtElementCtrl;
			txtCtrl.value = results[0];
			this.showControl( "COUNTY", "TEXT" );
			this.countyChanged( results[0]);
		} else {
			//change city
			dropDown = this.getDropDown(this.GROUP_NAME_CITY);
			txtCtrl = dropDown.cityTxtElementCtrl;
			txtCtrl.value = results[0];
			this.showControl( "CITY", "TEXT" );
			this.cityChanged( results[0]);
		}
	} else {
		//show dropdown
		if( this.needCounty ){
			dropDown = this.getDropDown(this.GROUP_NAME_COUNTY);
			dropDown.populateList( dropDown.countySelElementCtrl, results );

			//show dropdown
			this.showControl( "COUNTY", "DROPDOWN" );
			this.countyChanged( dropDown.countySelElementCtrl.value );
		} else {
			//change city
			dropDown = this.getDropDown(this.GROUP_NAME_CITY);
			dropDown.populateList( dropDown.citySelElementCtrl, results );

			//show dropdown
			this.showControl( "CITY", "DROPDOWN" );
			this.cityChanged( dropDown.citySelElementCtrl.value );
		}
	}

	return true;
}

ZipRelatedDropDownsHolder.prototype.countyChanged = function ( county ){
	if( county == ZipRelatedDropDown.SELECT_ELEMENT ){
		this.currentCounty = "";
		results = null;
	} else {
 		this.currentCounty = county;
   		if( dojo.string.trim(county) == "" ){
   			results = null;
   		} else {
			results = retrieveDropdownArray( this.jsonZipRecords, this.currentState, this.needCounty, county );
		}
	}

	var dropDown, txtCtrl;

	dropDown = this.getDropDown(this.GROUP_NAME_COUNTY);
	dropDown.countyTxtElementCtrl.value = this.currentCounty;


	if (results==null ||  results instanceof Error){
		this.showControl( "CITY", "NONE" );
		this.cityChanged( "" );
		return false;
	} else if( results.length < 1 ){
		this.showControl( "CITY", "NONE" );
		this.cityChanged( "" );
		return false;
	} else if(  results.length == 1 ) {
		//show textbox
		dropDown = this.getDropDown(this.GROUP_NAME_CITY);
		txtCtrl = dropDown.cityTxtElementCtrl;
		txtCtrl.value = results[0];
		this.showControl( "CITY", "TEXT" );
		this.cityChanged( results[0]);
	} else {
		//show dropdown
		dropDown = this.getDropDown(this.GROUP_NAME_CITY);
		dropDown.populateList( dropDown.citySelElementCtrl, results );

		//show dropdown
		this.showControl( "CITY", "DROPDOWN" );
		this.cityChanged( dropDown.citySelElementCtrl.value );
	}

	return true;
}

ZipRelatedDropDownsHolder.prototype.cityChanged = function ( city ){
	var dropDown = this.getDropDown(this.GROUP_NAME_CITY);
	if( city == ZipRelatedDropDown.SELECT_ELEMENT ){
		dropDown.cityTxtElementCtrl.value = "";
	} else {
		dropDown.cityTxtElementCtrl.value = city;
	}

	if( this.hasTaxRate() ){
		var ctrl = dojo.byId(this.taxRateElementName);
		if( (city == ZipRelatedDropDown.SELECT_ELEMENT) ||
						(dojo.string.trim(city) == "") ){
			ctrl.value = "";
			return true;
		} else {
			results = retrieveDropdownArray( this.jsonZipRecords, this.currentState, this.needCounty, this.currentCounty, city );
			if (results==null ||  results instanceof Error){
				ctrl.value = "";
				dojo.byId("ErrorSummary").innerHTML = "Can not get tax rate.";
				return false;
			} else if( results.length == 1 ){
				//get Tax Rate
				ctrl.value = results[0];
				return true;
			} else {
				ctrl.value = "";
				dojo.byId("ErrorSummary").innerHTML = "Can not get tax rate.";
				return false;
			}
		}
	}
}

ZipRelatedDropDownsHolder.prototype.showControl=function (/*string*/ dataType, /*string*/ctrlType){
	var selCtrl, txtCtrl;
	if( dataType == "STATE" ){
		var dropDown = this.getDropDown(this.GROUP_NAME_STATE);
		selCtrl = dropDown.stateSelElementCtrl;
		txtCtrl = dropDown.stateTxtElementCtrl;
	} else if( dataType == "COUNTY" ){
		var dropDown = this.getDropDown(this.GROUP_NAME_COUNTY);
		selCtrl = dropDown.countySelElementCtrl;
		txtCtrl = dropDown.countyTxtElementCtrl;
	} else if( dataType == "CITY" ){
		var dropDown = this.getDropDown(this.GROUP_NAME_CITY);
		selCtrl = dropDown.citySelElementCtrl;
		txtCtrl = dropDown.cityTxtElementCtrl;
	}

	if( ctrlType == "NONE" ){
		selCtrl.style.display = 'none';
		txtCtrl.style.display = 'none';
	} else if ( ctrlType == "TEXT" ){
		selCtrl.style.display = 'none';
		txtCtrl.style.display = 'block';
	} else if ( ctrlType == "DROPDOWN" ){
		selCtrl.style.display = 'block';
		txtCtrl.style.display = 'none';
	}
}

ZipRelatedDropDownsHolder.prototype.addState=function ( /*string*/selElementName, /*string*/txtElementName){
	var dropDown = this.getDropDown(this.GROUP_NAME_STATE);
	dropDown.stateSelElementName = selElementName;
	dropDown.stateTxtElementName = txtElementName;
}

ZipRelatedDropDownsHolder.prototype.addCounty=function ( /*string*/selElementName, /*string*/txtElementName){
	var dropDown = this.getDropDown(this.GROUP_NAME_COUNTY);
	dropDown.countySelElementName = selElementName;
	dropDown.countyTxtElementName = txtElementName;
}

ZipRelatedDropDownsHolder.prototype.addCity=function ( /*string*/selElementName, /*string*/txtElementName){
	var dropDown = this.getDropDown(this.GROUP_NAME_CITY);
	dropDown.citySelElementName = selElementName;
	dropDown.cityTxtElementName = txtElementName;
}

ZipRelatedDropDownsHolder.prototype.hasTaxRate=function (){
	if( this.taxRateElementName == "" ){
		return false;
	} else {
		return true;
	}
}

ZipRelatedDropDownsHolder.prototype.getDropDown=function (/*string*/ groupName){
	for (var i =0; i<this.dropDowns.length;i++){
		if (this.dropDowns[i].groupName==groupName){
			return this.dropDowns[i];
		}
	}

	var dropDown = new ZipRelatedDropDown (groupName);
	this.dropDowns.push(dropDown);
	return dropDown;
}

//helper functions
function retrieveDropdownArray( jsonZipRecords, state, needCounty, county, city ){
	var strQuery = "$[?(@.state='";

	if( city != null ){
		//return tax
		if( dojo.string.trim( city ) == "" ){
			return null;
		}

		strQuery = strQuery + state +  "' & @.county='" + county + "' & @.city='" + city + "')][=tax]";
	} else if( county != null ){
		//return city
		if( dojo.string.trim( county ) == "" ){
			return null;
		}
		strQuery = strQuery + state +  "' & @.county='" + county + "')][=city]";
	} else if( state != null ){
		if( dojo.string.trim( state ) == "" ){
			return null;
		}

		if( needCounty ){
			//return county
			strQuery = strQuery + state + "')][=county]";
		} else {
			//return city
			strQuery = strQuery + state + "')][=city]";
		}
	} else if( jsonZipRecords != null ){
		//return state
		strQuery = "$[=state]"; //$.state";
	} else {
		return null;
	}

	var results;
	try{
		//results = dojox.jsonPath.query(jsonZipRecords, strQuery, {evalType:"RESULT"});
		results = dojox.json.query(strQuery,jsonZipRecords);
		//results = dojo.toJson(results);
	} catch( e ){
		return null;
	}


	if( results.length == 0 ){
		return null;
	} else{
		results = eliminateDuplicates(results);
	}

	return results;
}

/* end of QC1368 */
/*******************************************************************************************************/
/* QC1387
 * by q04000, 08/22/2011
 * For some reason users have been entering credit card info on the online repair form in fields like Name, 
 * Address, comments, etc.   Should put in detection code on form submit to look for 'credit card like' information 
 * and alert user.
 */
var CCValidateRegExp = {};
var CCDetectRegExp = {};

//this function has to be called by referencing JSP.
//basically it will initialize resources, like CCValidateRegExp object.
//because the value of RT_CC_TYPE_VISA is from java code, so has to be
//set explicitly after page loaded.
function initClientFormValidationJsFile(){
	// regexp's to detect/verify what kind of card it is
	// and what algorithm to use to validate each one
	// note: obj = {key1: val1, key2: val2} and /regexp/ syntax is IE/NN 4+ only!
	// define any new kind of card here
	CCValidateRegExp[RT_CC_TYPE_VISA] = {regexp: /^4\d{12}(\d{3})?$/ , algorithm: mod10};
	CCValidateRegExp[RT_CC_TYPE_MASTER] = {regexp: /^5[1-5]\d{14}$/ , algorithm: mod10};
	CCValidateRegExp[RT_CC_TYPE_DISCOVER] = {regexp: /^6011\d{12}$/ , algorithm: mod10};
	CCValidateRegExp[RT_CC_TYPE_AMEX] = {regexp: /^3[47]\d{13}$/ , algorithm: mod10};

	CCDetectRegExp[RT_CC_TYPE_VISA] = {regexp: '4\\d{12}(\\d{3})?'};
	CCDetectRegExp[RT_CC_TYPE_MASTER] = {regexp: '5[1-5]\\d{14}'};
	CCDetectRegExp[RT_CC_TYPE_DISCOVER] = {regexp: '6011\\d{12}'};
	CCDetectRegExp[RT_CC_TYPE_AMEX] = {regexp: '3[47]\\d{13}'};

	//  'Diners Club/Carte Blanche': {regexp: /^3(0[0-5]|[68]\d)\d{11}$/, algorithm: mod10},
	//  enRoute:            {regexp: /^2(014|149)\d{11}$/,                algorithm: none},
	//  JCB:                {regexp: /^(3\d{15}|2131\d{11}|1800\d{11})$/, algorithm: mod10}
}

function detectCCNumberByCardType( exp, text ){
	var strExp = exp;

	//extract RegExp to detect CC Number in a long string.
	//so need to remove '/^' and '$/' in the expression.
//	var re = new RegExp('(^(/\\^))|((\\$/)$)', 'g');
//	strExp = strExp.replace(re, '');

	//find the cc number and return.
    	re = new RegExp(strExp);
	var m = re.exec(text);
	if (m == null) {
		return null;
	} else {
	    return m[0];
	}
}

function detectCCNumberWithAllCardType(str){
	//please check Master before VISA.
	var exp;
	exp = CCDetectRegExp[RT_CC_TYPE_MASTER].regexp.toString();
	strCCNumber = detectCCNumberByCardType( exp, str );
	if( strCCNumber != null ){
		return strCCNumber;
	}

	exp = CCDetectRegExp[RT_CC_TYPE_AMEX].regexp.toString();
	strCCNumber = detectCCNumberByCardType( exp, str );
	if( strCCNumber != null ){
		return strCCNumber;
	}

	exp = CCDetectRegExp[RT_CC_TYPE_DISCOVER].regexp.toString();
	strCCNumber = detectCCNumberByCardType( exp, str );
	if( strCCNumber != null ){
		return strCCNumber;
	}

	var exp = CCDetectRegExp[RT_CC_TYPE_VISA].regexp.toString();
	var strCCNumber = detectCCNumberByCardType( exp, str );
	if( strCCNumber != null ){
		return strCCNumber;
	}

	return null;
}

function detectCCNumberInText(txt){
	var re1 = new RegExp('\\W', 'g');
	var strText = txt.replace(re1, '');
	if( strText == '' ){
		return null;
	}
	return detectCCNumberWithAllCardType( strText );
}

/////
//
// GENERIC CREDIT CARD VERIFY FUNCTIONS that could be used anywhere:
//

//
// the 'mod10' and 'none' algorithms:
//

// optimized LUHN Formula / mod 10 algorithm
// two digits of numbers 10-19 added up = that number minus 10 plus 1, or simply minus 9
// hence the ability to roll the whole addition routine into a single line! ;o)
function mod10 (ccnum) {
  var sum = 0;
  for (var i = ccnum.length - 1; i >= 0; i -= 2)
    sum += ccnum.charAt(i) * 1 + ccnum.charAt(i - 1) * 2 - (ccnum.charAt(i - 1) >= 5 ? 9 : 0);
  return ( sum % 10 == 0 );
}

// blank do-nothing algorithm for enRoute
function none () { return true }

// define any new kind of checksum/checkdigit algorithm here

//
// small useful wrappers for above stuff:
//

// check if card is of supplied type and if number is ok
// note: type must be specified exactly as defined above
// returns true or false
function checkCardType (CC, n, t) {
  return ( CC[t] && CC[t].regexp.test(n) && CC[t].algorithm(n) );
}

// check if supplied card number is ok
// returns type (which is true) or null (which is false)
function checkCard (CC, n) {
  for (var t in CC) if (CC[t].regexp.test(n)) return (CC[t].algorithm(n) ? t : null); return null
}

// more optimized get card type, but doesn't check the algorithm
// returns card type or null
function getCardType (CC, n) {
  for (var t in CC) if (CC[t].regexp.test(n)) return t; return null
}	

/* end of QC1387 */
/*******************************************************************************************************/


