// (C) 2003 Ken McCormack P21 www.p21.com.au ///* User fields are defined as follows:fields[etc] = new formElementObj (field_name,user_friendly_ name,validation_type,default_value,minimum_length, 				maximum_length, empty_field_error_message,class_name,value_array); wherefield_name = matches the name of the form field exactlyuser_friendly_name = the user readable name of the field, for use in error messages, eg 'Email Address'validation_type = type of validation required for the field; valid options are		"string" - 	string will be required that is between minimum and maximum length	"select" - 	requires a selected index of the lement fieldName to be between minimum and maximum length	"email" - 	same as for string, but requires a valid email address	"ccdate" - 	credit card date validation - this will look for a date of the form "xx-MM-YYYY".				An error is returned if the date is empty or in th past. 	"ccnumber"  credit card number vallidation - this uses a mod10 checkdigit sum to validate CC numbersdefault_value	= the defult value passed into the rendered element - ie.e inner text of a text field, checkbox status etcminimum length - minimum string length, numeric quantity or select index				- for checkbox this is true or false for whether should be checked / uncheckedmaximum length - minimum string length, numeric quantity or select index				- for checkbox this is the checked value				empty field error message - the message generated when the specified field is empty; for example, a string validated 	will generate the following error messages:	fields[fields.length] = new formElementObj ("el1","Element 1","string",2,5,"Please enter Element 1);	empty field - generates error prompt -  'Please enter Element 1'	string, length 1 generates error  -		'Error - minimum length for Element 1 is 2 characters' 	string, length 6 generates error  -		'Error - maximum length for Element 1 is 5 characters' 	NB: When this field is omitted, the form element is no longer required by validation - i.e. it becomes an optional field	Required fields receive an asterix.class_name = the CSS class applied to the elementvalue_array = an array passed containing value-text pairs of select box OPTION elementsNote - fields will be validated in the order they are declared - this should be the same order as they are displayed on the HTML form*/bDebug = false;function displayFields(){	// disply customer form fields as set by fields array	for (var i=0; i<fields.length; i++)	{			displaySingleField(fields[i],false);	}	}function showSingleFormElement(fieldName){	// search for index from form field name	for (var i=0; i<fields.length; i++)	{			if (fields[i].fieldName == fieldName) 		{				displaySingleField(fields[i],"true"); return true; 		}			}	}function displaySingleField(formElmObj, fieldOnly){		var formStr="";  // form element		var requiredString = "";				if (bDebug) alert ("Adding "+ formElmObj.fieldName + " type= " + formElmObj.typeRequired)		if (formElmObj.onChangeAction != "")		{			var onChangeAction = " onChange=\"" + formElmObj.onChangeAction + "\"";			}				switch (formElmObj.typeRequired)		{			case "string" 	:			case "email" 	:			case "numeric"	:			case "ccnumber" :  	formStr="<input name=\""+ formElmObj.fieldName +"\" id=\""+ formElmObj.fieldName +"\" type=\"text\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.defaultValue+"\"" + onChangeAction + "/>"; 								break;						case "password" :  	formStr="<input name=\""+ formElmObj.fieldName +"\" id=\""+ formElmObj.fieldName +"\" type=\"password\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.defaultValue+"\"" + onChangeAction + "/>"; 								break;						case "file"		:	formStr="<input name=\""+ formElmObj.fieldName +"\" id=\""+ formElmObj.fieldName +"\" type=\"file\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.defaultValue+"\"" + onChangeAction + "/>"; 								if (formElmObj.maxValue != "")									document.write("<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\""+ formElmObj.maxValue +"\">");								break;											case "select" 	: 	formStr="<select name=\""+ formElmObj.fieldName +"\" id=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\"" + onChangeAction + ">" + selectOption(formElmObj.valueArray,formElmObj.defaultValue) + "</select>"; break; 						case "ccdate" 	: 	// render hidden field where segmented fields are concatenated									formStr="<input type=\"hidden\" name=\""+ formElmObj.fieldName +"\" value=\"00-00-0000\">";								// render segmeted fields and onchange events calling updateDate function, which updates hidden 'parent' element above								formStr+= "Month: " + splitCCDateSelectElement("cc_expiry_month",formElmObj.fieldName,"month") + " Year: " +  splitCCDateSelectElement("cc_expiry_year",formElmObj.fieldName,"year");								// "cc_expiry_month" + i is passed in case there are may be multiple date fields used								break;						case "date" 	: 	// render hidden field where segmented fields are concatenated									// parse default value								if (formElmObj.defaultValue == "")									formElmObj.defaultValue = "00-00-0000";																		if (formElmObj.defaultValue.indexOf("-") != -1) var defaultArray = formElmObj.defaultValue.split("-");									if (formElmObj.defaultValue.indexOf("/") != -1) var defaultArray = formElmObj.defaultValue.split("/");									if (formElmObj.defaultValue.indexOf(":") != -1) var defaultArray = formElmObj.defaultValue.split(":");																		var defaultDay = defaultArray[0]; var defaultMonth = defaultArray[1]; var defaultYear = defaultArray[2];  																formStr="<input type=\"hidden\" name=\""+ formElmObj.fieldName +"\" id=\""+ formElmObj.fieldName +"\" value=\"" + formElmObj.defaultValue +"\">";								// render segmeted fields and onchange events calling updateDate function, which updates hidden 'parent' element above								formStr += splitDateSelectElement("dob_day"+formElmObj.fieldName, formElmObj.fieldName,"day",defaultDay) + "&nbsp" + splitDateSelectElement("month_day"+formElmObj.fieldName,formElmObj.fieldName,"month",defaultMonth) + "&nbsp;" + splitDateSelectElement("dob_year"+formElmObj.fieldName,formElmObj.fieldName,"year",defaultYear);								// "cc_expiry_month" + i is passed in case there are may be multiple date fields used								break;						case "submit"	:	// write submite button - default value is rendered into button text								formStr="<input type=\"submit\" name=\""+ formElmObj.fieldName +"\" value=\""+formElmObj.defaultValue+"\" class=\"button\">";								break;			case "subheading":  	formStr="";								break;			case "calculated":  formStr="<input name=\""+ formElmObj.fieldName +"\" type=\"text\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.defaultValue+"\" readonly/>"; 								break;			case "hidden":  	formStr="<input name=\""+ formElmObj.fieldName +"\" type=\"hidden\" value=\""+formElmObj.defaultValue+"\"/>"; 								break;			case "text-area":  formStr="<textarea rows=\"5\" name=\""+ formElmObj.fieldName +"\"  id=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\">" + formElmObj.defaultValue+ "</textarea>"; 								break;			case "checkbox":  formStr="<input type=\"checkbox\" name=\""+ formElmObj.fieldName +"\"  id=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\" value=\""+formElmObj.maxValue+"\"  onClick=\""+formElmObj.onChangeAction+"\" "+ formElmObj.defaultValue +"/>"; 								break;											case "radio":  		for (var k=0; k<formElmObj.valueArray.length;k+=2)								{									formStr += "<div class=\"radioname\">"+formElmObj.valueArray[k+1]+"</div>";									if (formElmObj.defaultValue == formElmObj.valueArray[k])										formStr += "<div class=\"radiofield\"><input type=\"radio\" name=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\" CHECKED/></div>";											else												formStr += "<div class=\"radiofield\"><input type=\"radio\" name=\""+ formElmObj.fieldName +"\" class=\""+ formElmObj.className + "\"/></div>";								}								break;			case "quiz" 	:	formStr= getQuizElements(fields[i]);		}				if (fieldOnly == "true") 		{			// only write the element itself			document.write(formStr);			return true; // do no more 		}				// form element string now built, last of all render element and name into DIVs within the page		if (formElmObj.errorMsg) requiredString = "*"; // append asterix if this is a required field				if (formElmObj.typeRequired == "checkbox")		{				document.write("<div class=\"formRow\">");				document.write("<div class=\"checkboxright\">" + formStr + "</div>");				document.write("<div class=\"checkboxleft\">" + formElmObj.friendlyName + requiredString + "</div>");				document.write("</div>");		}		else if (formElmObj.typeRequired == "quiz")		{				document.write("<div class=\"formRow QuizRow\">"); 			// quiz question			document.write("<div class=\"quizheader\">" + formElmObj.friendlyName + "</div>");			// options			document.write( formStr + "</div>");		}		else if (formElmObj.typeRequired == "submit")		{	// button			// write left and right aligned text field pairs			document.write("<div class=\"formRow submitRow\">" + formStr + "</div>");		}		else		{			document.write("<div class=\"formRow\">"); 			if (formStr != "") 			{				// write left and right aligned text field pairs				formStr = "<div class=\"formleft\">" + formStr + "</div>";				document.write("<div class=\"textleft\">" + formElmObj.friendlyName + requiredString + "</div>" + formStr );				document.write("</div>");			}			else			{	// write signle strap line				document.write("<div class=\"subheading\">" + formElmObj.friendlyName + "</div></div>");			}		}}function getQuizElements(fieldObj){	var optionString = ""; 	var selString ="";	var ctr=0;	var selectedValue = fieldObj.defaultValue;	if (fieldObj.defaultValue == "") selectedValue = -1;		if (bDebug) alert ("Allow multiple for " + fieldObj.fieldName + "? : " + fieldObj.allowMultiple);	var hiddenDefault="";		// hidden element	if (selectedValue != "-1") hiddenDefault = fieldObj.valueArray[(selectedValue * 2)];	if (hiddenDefault == "undefined") hiddenDefault = ""; // ??	//if (bDebug) optionString += "<input type=\"text\" name=\""+ fieldObj.fieldName +"\"value=\""+ hiddenDefault + "\" style=\"width: 300px;\"/>\n";		//else 		optionString += "<input type=\"hidden\" name=\""+ fieldObj.fieldName +"\" value=\""+ hiddenDefault + "\"/>\n";	for (var i=0; i<fieldObj.valueArray.length; i+=2)	{		if (ctr == selectedValue) 		{			selString = " CHECKED";		}		else selString = "";  // default value of select		ctr++;		optionString += "<div class=\"quizoption\">\n";		optionString += "<div class=\"quizright\">" + "<input type=\"checkbox\" name=\""+ fieldObj.fieldName + "_" + ctr +"\" value=\""+ fieldObj.valueArray[i] + "\"" + selString + " onClick=\"updateHiddenQuizField('"+fieldObj.fieldName+"','"+ "_" + ctr+ "','"+ (fieldObj.valueArray.length / 2)+"','"+fieldObj.allowMultiple+"')\"></div>\n";		optionString += "<div class=\"quizleft\">" + fieldObj.valueArray[i+1] + "</div>\n";		optionString += "</div>\n"; // quizoption	}	// alert ("151 Adding " + optionString);	return optionString;}function updateHiddenQuizField(a,b,numberOfFields,allowMultiple){	// copies b into hidden field a //	if (bDebug) 	if (bDebug) alert ("Update call a=" + a + " b=" + b  + "Fields : " + numberOfFields + " allow multiple " + allowMultiple)		if (allowMultiple == "false")	{	// selections must be unique		document.form1.elements[a].value = document.form1.elements[a+b].value;			for (var j=1; j<=numberOfFields; j++)		{			// alert ("value " + j + "(" + (a + j) + ") =" + document.form1.elements[(a + j)].value);						if ("_" + j ==  b) 			{				if (document.form1.elements[(a + "_" + j)].checked) 				{	// reversed because click checks box					document.form1.elements[(a + "_" + j)].checked = true;				}				else				{					document.form1.elements[(a + "_" + j)].checked = false;					// clear parent element					document.form1.elements[a].value = "";				}			}			else			{				// alert ("unchecking elements[" + (a + "_" + j) + "]");				document.form1.elements[(a + "_" + j)].checked = false;				}		}	}	else	{	// selections can be multiple 		var valueString = "";		for (var j=1; j<=numberOfFields; j++)		{	// concatenate value string from selected fields			if (bDebug) alert ("element " + (a + "_" + j) + "checked? "  + document.form1.elements[(a + j)].checked);			if (document.form1.elements[(a + "_" + j)].checked)			{				if (bDebug) alert ("Adding: " + document.form1.elements[(a + "_" + j)].value );				valueString += document.form1.elements[(a + "_" + j)].value + " "; 			}		}		if (bDebug) alert ("valuestring= " + valueString);		document.form1.elements[a].value = valueString;	}}function selectOption(valueArray,selectedValue){	// construct a string of option html elements corrpesponding to value and text pair array valueArray	// selectedValue contains the index of the default element		var optionString = ""; 	var selString ="";	var ctr=0;			for (var i=0; i<valueArray.length; i+=2)	{			if (valueArray[i] == selectedValue) 			{				selString = "selected";			}			else selString = "";  // default value of select			ctr++;						optionString += "<option value=\""+ valueArray[i] + "\"" + selString + ">" + valueArray[i+1]+ "</option>\n";	}		return optionString;}function splitCCDateSelectElement(elName,elParent,type){	// generate month or year select box using current year as the base value	 // type is month or year	 // parent is the hidden element to be updated on change of this element 	  var start = 1;  var end=1;	  var now = new Date();	   	  if (type == "year") { start = now.getYear();  end = start + 5 }  // parameters of year loop	  if (type == "month") { start = 1;  end = 12 }  // parameters of month loop	  	  var elString = "<select name=\""+ elName +"\" onchange=\"updateDate('" + elName + "','" + elParent + "','" + type + "')\">";	  elString +=  "<option value=\"\"></option>\n"; // initial blank value	  for (var i = start; i<end+1; i++)	       elString +=  "<option value=\"" + i + "\">"+ i + "</option>\n";                  elString += "</select>";	  return elString;}function splitDateSelectElement(elName,elParent,type,defaultValue){	// generate month or year select box using current year as the base value	 // type is month or year	 // parent is the hidden element to be updated on change of this element 	  var start = 1;  var end=1;	  var now = new Date();	  	  if (type == "day") { start = 1;  end = 31; }  	  if (type == "year") { start = 1932;  end = 2006; }  // parameters of year loop	  if (type == "month") { start = 1;  end = 12 }  // parameters of month loop	  	  var elString = "<select name=\""+ elName +"\" onchange=\"updateDate('" + elName + "','" + elParent + "','" + type + "')\">";	  elString +=  "<option value=\"\"></option>\n"; // initial blank value	  for (var i = start; i<end+1; i++)	  {		  if (i == defaultValue) 		  elString +=  "<option value=\"" + i + "\" SELECTED>"+ i + "</option>\n";		  	else		  		elString +=  "<option value=\"" + i + "\">"+ i + "</option>\n";	  }      elString += "</select>";	  return elString;}// update hidden date field on change of a day / month / year parameterfunction updateDate(elName,elParent,type){	// this function is called onChange of segmented date fields	// it updates the value of the element's parent hidden field used for data and validation	 	var hiddenField = document.form1.elements[elParent].value; // ", default value=" + selectedValue);	var valueField = document.form1.elements[elName].value; // ", default value=" + selectedValue);	if (bDebug) alert ("Date field changed is " + elName + " (type=" + type + ") value=" + valueField + "\nparent hidden element is " + elParent + " value=" + hiddenField);		// initially hiddenField is 00-00-0000	var splitField = hiddenField.split("-");	// construct new date from changed field value	switch (type) 	{		case "day"		:	hiddenField= valueField + "-" + splitField[1] + "-" + splitField[2]; break; // not currently used		case "month"	: 	hiddenField= splitField[0] + "-" + valueField + "-" + splitField[2]; break;		case "year"		: 	hiddenField= splitField[0] + "-" + splitField[1] + "-" + valueField; break;	}	// update hidden field	document.form1.elements[elParent].value = hiddenField; 	if (bDebug) alert ("Date field changed to " + hiddenField);}// define formElement class which holds all field and validation datafunction formElementObj(fieldName,friendlyName,typeRequired,defaultValue,minValue,maxValue,errorMsg,className,valueArray,onChangeAction){	this.fieldName = fieldName;				// name of field on form	this.friendlyName = friendlyName;		// name of field for error messages	this.typeRequired = typeRequired;		// type of field or value required	this.defaultValue = defaultValue;		// default value of form field	this.minValue = minValue;				// min value or length, depenmding on type	this.maxValue = maxValue;				// max value or length, ...	this.errorMsg = errorMsg;				// error message for a null or empty field	this.validate = formElementValidate;	// validate function called on form submission	this.className = className; 			// class applied to form element	this.valueArray = valueArray;			// value array for multi-value elements, eg select or radio button arrays	this.onChangeAction	= onChangeAction;		//if (typeRequired == "checkbox") alert ("Maxvalue for " + fieldName  + " is " + maxValue);}function formElementValidate(formObj){	// direct validation to correct validation function for given 'data' type	// this would be more elegant using polymorphic methods, maybe inr JS 2.0...?	// but for now we have separate functions to validate string, select, email, cc expiry date and cc number elements 		if (!this.errorMsg) return true; // do not validate fields that are not required		switch (this.typeRequired)	{		case "string" 	: return validateString(formObj,this);		case "password" : return validateString(formObj,this);		case "file" 	: return validateString(formObj,this);		case "select" 	: return validateSelect(formObj,this);		case "email" 	: return validateEmail(formObj,this);		case "ccdate" 	: return validateDate(formObj,this);		case "ccnumber" : return validateCCNumber(formObj,this);		case "numeric"  : return validateNumber(formObj,this);		case "hidden"   : return true; // validateNumber(formObj,this);		case "text-area": return validateString(formObj,this); 		case "checkbox"	: return validateCheckbox(formObj,this); 		case "button"	: return true;		case "submit"	: return true;		case "quiz"		: return validateQuiz(formObj,this); 	}	// type not known 	alert ("Error - form type " + this.typeRequired + " not recognised for " + this.fieldName);	return false;}// validate string elementfunction validateString(formObj,fmElement){	// validate contents of a string field	// field must be between min and max length		//alert ("Validating " + fmElement.fieldName);	var fieldValue = formObj[fmElement.fieldName].value;	//alert (fmElement.fieldName + " has value " + fieldValue);		//if (bDebug) alert ("Validating " + fmElement.fieldName + " which has value " + fieldValue);	if (fieldValue == "") 	{		alert(fmElement.errorMsg); return false;	}	if (fieldValue.length < fmElement.minValue) 	{			alert("Error - minimum length for " + fmElement.friendlyName + " is " + fmElement.minValue + " characters");		return false;	}		if (fieldValue.length > fmElement.maxValue) 	{			alert("Error - maximum length for " + fmElement.friendlyName + " is " + fmElement.maxValue + " characters");		return false;	}	return true;}function validateNumber(formObj,fmElement){	// number validation - not used on current form	var fieldValue = formObj[fmElement.fieldName].value;	if (fieldValue == "") 	{		alert(fmElement.errorMsg); return false;	}		if (fieldValue < fmElement.minValue) 	{			alert("Error - minimum value for " + fmElement.friendlyName + " is " + fmElement.minValue);		return false;	}		if (fieldValue > this.maxValue) 	{			alert("Error - maximum value for " + fmElement.friendlyName + " is " + fmElement.maxValue);		return false;	}	return true;}function validateCheckbox(formObj,fmElement){	// validate select box contents by checking the selectedIndex is between min and max values	var fieldValue = formObj[fmElement.fieldName].checked;		if (fieldValue.toString ==  fmElement.minValue) 	{			alert(fmElement.errorMsg); 		return false;	}	return true;}function validateSelect(formObj,fmElement){	// validate select box contents by checking the selectedIndex is between min and max values	var fieldValue = formObj[fmElement.fieldName].selectedIndex;		if (fieldValue < fmElement.minValue || fieldValue > fmElement.maxValue) 	{			alert(fmElement.errorMsg); 		return false;	}	return true;}function validateEmail(formObj,fmElement){	// validate email field using a regexp test		var fieldValue = formObj[fmElement.fieldName].value;	if (fieldValue == "") { alert(fmElement.errorMsg); return false; }	// use regular expression to test for email validity	var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ 	if (!re.test(fieldValue)) 	{		alert("Error - " + fmElement.friendlyName + " appears to be invalid."); return false;	}	return true;}function isEmail(fieldValue){	var re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ 	if (re.test(fieldValue)) return true		else return false;}function validateDate(formObj,fmElement){	// validate CC Date - month and year must be in the future	var fieldValue = formObj[fmElement.fieldName].value;	var dateFields = fieldValue.split("-");	var now = new Date;	// getMonth is 0-11 i.e. month value -1	if (parseInt(dateFields[2]) < now.getYear() || (dateFields[2] == now.getYear() && dateFields[1] < (parseInt(now.getMonth())+1)))	{		alert(fmElement.errorMsg); return false;	}	return true;}function validateCCNumber(formObj,fmElement){	// validate credit card number	// this script does not macth a given number prefix with the CCnumber type and number length etc	// this would be needed for a more watertight check		var fieldValue = formObj[fmElement.fieldName].value;	if (fieldValue == "") { alert(fmElement.errorMsg); return false; }	if (parseInt(fieldValue) == 0) { alert(fmElement.errorMsg); return false; }		// remove spaces and non numeric characters	var reg = /[^0-9]/g	fieldValue = fieldValue.replace(reg,"");		if (fieldValue == "") {	alert(fmElement.errorMsg); return false; }	// detect whether debug entry	if (fieldValue == "9999") return true;	// perform mod10 checksum	// for simplicity assume correct length is always 16, though this may vary	      var checkSum = 0;      //  Add even digits in even length strings or odd digits in odd length strings      for (loc=1-(fieldValue.length % 2); loc < fieldValue.length; loc+=2) 	  {		 var val = parseInt(fieldValue.substr(loc, 1));		 if (bDebug) alert ("adding " + val);		 checkSum += val;      }      // Add odd digits in even length strings and vice versa	for (loc=fieldValue.length % 2; loc < fieldValue.length; loc+=2)  	{         	var val = parseInt(fieldValue.substr(loc, 1)) * 2;			if (bDebug) alert ("adding " + val + "* 2");			if (val < 10) checkSum += val;				else  checkSum += val - 9;    }		if (bDebug) alert ("Total checksum = " + checkSum);	if (checkSum % 10 != 0) { alert("Error - " + fmElement.friendlyName + " appears to be invalid."); return false; } 	return true;}function validate_form(){	// form validation engine	var formObj = document.form1;		for (i=0;i<fields.length;i++) 	{		if (!fields[i].validate(formObj)) return false;		}		return true}function displayRoundTotal(val){	var total = Math.round(100*val)/100;	var displayStr = total;	// add extra zero to signle decimal	if 	(total*10== parseInt(total*10))		displayStr = total + "0";	// add decimal places to integer	if (total==parseInt(total))		displayStr = total + ".00";	return displayStr;}// define value-display pair arrays for select field elementsvar countryArray = new Array ("","Please select...","Australia","Australia","Algeria","Algeria","American Samoa","American Samoa","Argentina","Argentina","Armenia","Armenia","Austria","Austria","Bahamas","Bahamas","Bahrain","Bahrain","Bangladesh","Bangladesh","Barbados","Barbados","Belarus","Belarus","Belgium","Belgium","Belize","Belize","Bermuda","Bermuda","Bolivia","Bolivia","Brazil","Brazil","Brunei Darussalam","Brunei Darussalam","Cambodia","Cambodia","Canada","Canada","Chile","Chile","China","China","Colombia","Colombia","Croatia","Croatia","Cuba","Cuba","Cyprus","Cyprus","Czech Republic","Czech Republic","Denmark","Denmark","Djibouti","Djibouti","Dominican Republic","Dominican Republic","East Timor","East Timor","Ecuador","Ecuador","Egypt","Egypt","El Salvador","El Salvador","Equatorial Guinea","Equatorial Guinea","Eritrea","Eritrea","Estonia","Estonia","Ethiopia","Ethiopia","Falkland Islands","Falkland Islands","Fiji","Fiji","Finland","Finland","France","France","French Guiana","French Guiana","Frenh Southern Territories","French Southern Territories","FYROM","FYROM","Gabon","Gabon","Gambia","Gambia","Georgia","Georgia","Germany","Germany","Ghana","Ghana","Gibraltar","Gibraltar","Greece","Greece","Greenland","Greenland","Grenada","Grenada","Guadeloupe","Guadeloupe","Guam","Guam","Guinea","Guinea","Guyana","Guyana","Haiti","Haiti","Holland","Holland","Honduras","Honduras","Hong Kong","Hong Kong","Hungary","Hungary","Iceland","Iceland","India","India","Indonesia","Indonesia","Iran","Iran","Iraq","Iraq","Ireland","Ireland","Israel","Israel","Italy","Italy","Jamaica","Jamaica","Japan","Japan","Jordan","Jordan","Kazakhstan","Kazakhstan","Kenya","Kenya","Kiribati","Kiribati","Korea","Korea","Kuwait","Kuwait","Latvia","Latvia","Lebanon","Lebanon","Lesotho","Lesotho","Liberia","Liberia","Libyan Arab Jamahiriya","Libyan Arab Jamahiriya","Liechtenstein","Liechtenstein","Lithuania","Lithuania","Luxembourg","Luxembourg","Madagascar","Madagascar","Malawi","Malawi","Malaysia","Malaysia","Maldives","Maldives","Mali","Mali","Malta","Malta","Marshall Islands","Marshall Islands","Martinique","Martinique","Mauritania","Mauritania","Mauritius","Mauritius","Mayotte","Mayotte","Mexico","Mexico","Micronesia","Micronesia","Middle East","Middle East","Moldova","Moldova","Monaco","Monaco","Mongolia","Mongolia","Montserrat","Montserrat","Morocco","Morocco","Myanmar","Myanmar","Namibia","Namibia","Nauru","Nauru","Nepal","Nepal","Netherlands Antilles","Netherlands Antilles","New Caledonia","New Caledonia","New Zealand","New Zealand","Nicaragua","Nicaragua","Niger","Niger","Nigeria","Nigeria","Niue","Niue","Norfolk Island","Norfolk Island","Northern Africa","Northern Africa","Northern Mariana Islands","Northern Mariana Islands","Norway","Norway","Oman","Oman","Pakistan","Pakistan","Palau","Palau","Panama","Panama","Papua New Guinea","Papua New Guinea","Paraguay","Paraguay","Peru","Peru","Philippines","Philippines","Pitcairn","Pitcairn","Poland","Poland","Portugal","Portugal","Puerto Rico","Puerto Rico","Qatar","Qatar","Reunion","Reunion","Romania","Romania","Russia","Russia","Russian Federation","Russian Federation","Rwanda","Rwanda","Saint Helena","Saint Helena","Saint Kitts and Nevis","Saint Kitts and Nevis","Saint Lucia","Saint Lucia","Saint Pierre and Miquelon","Saint Pierre and Miquelon","Saint Vincent Grenadines","Saint Vincent Grenadines","Samoa","Samoa","San Marino","San Marino","Saudi Arabia","Saudi Arabia","Scotland","Scotland","Senegal","Senegal","Seychelles","Seychelles","Sierra Leone","Sierra Leone","Singapore","Singapore","Slovakia","Slovakia","Slovenia","Slovenia","Solomon Islands","Solomon Islands","Somalia","Somalia","South Africa","South Africa","Spain","Spain","Sri Lanka","Sri Lanka","Sudan","Sudan","Suriname","Suriname","Swaziland","Swaziland","Sweden","Sweden","Switzerland","Switzerland","Syrian Arab Republic","Syrian Arab Republic","Taiwan","Taiwan","Tajikistan","Tajikistan","Tanzania","Tanzania","Thailand","Thailand","Togo","Togo","Tokelau","Tokelau","Tonga","Tonga","Trinidad and Tobago","Trinidad and Tobago","Tunisia","Tunisia","Turkey","Turkey","Turkmenistan","Turkmenistan","Tuvalu","Tuvalu","Uganda","Uganda","Ukraine","Ukraine","United Arab Emirates","United Arab Emirates","United Kingdom","United Kingdom","United States of America","United States of America","Uruguay","Uruguay","Vanuatu","Vanuatu","Vatican City State","Vatican City State","Venezuela","Venezuela","Vietnam","Vietnam","Virgin Islands (British)","Virgin Islands (British)","Virgin Islands (U.S.)","Virgin Islands (U.S.)","Zimbabwe","Zimbabwe");
