/**************************************************************************************************
* QAS best practice proweb implementation application. This javascript is designed to be run with
* the accompanying html (as found in proweb.html). The code is split into generic objects (com.qas),
* logic (business), event handling (events) and presentation (interface). All style changes should
* be made through proweb.css.
* @author Toby Mostyn
*Modified for CAN AJAX: Robert Eaton (12/26/07)
// Edited by Jacob Tabor (11/14/08)
// Uses Address IDs from current page vs editing the HTML code itself
//Edit ID's on bottom of page
**************************************************************************************************/
// Set the "namespaces" (these mimic the java domain model)
var com = new Object();
com.qas = new Object();
var interface = new Object();
var business = new Object();
var events = new Object();

// Constant variables
com.qas.READY_STATE_UNINITIALISED = 0;
com.qas.READY_STATE_LOADING = 1;
com.qas.READY_STATE_LOADED = 2;
com.qas.READY_STATE_INTERACTIVE = 3;
com.qas.READY_STATE_COMPLETE = 4;
com.qas.PROMPTSET = "Default";
com.qas.MAXIMUM_CONNECTION_ATTEMPTS = 3;

// Variables set by the "constant" DOM objects (treated as variables)
com.qas.AJAXURL = document.getElementById("AJAXURL").value;
com.qas.ADDRESSLAYOUT = document.getElementById("ADDRESSLAYOUT").value;
com.qas.FORM_BUTTON_ID = document.getElementById("FORM_BUTTON_ID").value;
com.qas.RUN_AS_POPUP = document.getElementById("RUN_AS_POPUP").value;
com.qas.IGNORE_UNMATCHED_ADDRESSES = document.getElementById("IGNORE_UNMATCHED_ADDRESSES").value;
com.qas.IGNORE_CONNECTION_ERROR = document.getElementById("IGNORE_CONNECTION_ERROR").value;

//  Use original address text field ID's from calling page.   To Use:  Browser the current page without QAS.  View the source of the page and save the ID's of your Address Text Fields and input them here.
var LINEONECTL = document.getElementById("LINEONECTL").value;
var LINETWOCTL = document.getElementById("LINETWOCTL").value;
var LINETHREECTL = document.getElementById("LINETHREECTL").value;
var CITYCTL = document.getElementById("CITYCTL").value;
var STATECTL = document.getElementById("STATECTL").value;
var ZIPCTL = document.getElementById("ZIPCTL").value;
var COUNTRYCTL = document.getElementById("COUNTRYCTL").value;

promptMsg = "Validating Address Information...";

// All messages used by the application are stored as constants here for ease of manipulation
//added a function to set the messages for flexibility with CAN/USA AJAX..
events.setMessages = function()
{
	com.qas.COUNTRYSET = document.getElementById(COUNTRYCTL).value;
	
	if (com.qas.COUNTRYSET == "CAN") 
	{
		com.qas.MSG_PREMPARTIAL = "According to Canada Post the address you entered is missing important "
			+ "information.\<br\>\<b\>To correct this: <\/b\> please enter the missing "
			+ "information in the box below or choose one of the options on the right.";
		com.qas.MSG_PREMPARTIAL_ERROR = "The secondary number you entered could not be found. Please refer "
			+ "to list of options below.";
		com.qas.MSG_STREETPARTIAL = "According to Canada Post the street number you entered is either missing "
			+ "or incorrect. \<br\>\<b\>To correct this: <\/b\> please enter the street number in the box below or "
			+ "choose one of the options on the right to proceed.";
		com.qas.MSG_STREETPARTIAL_ERROR = "The street number you entered could not be found. Please refer "
			+ "to list of options below.";
		com.qas.MSG_MULITPLE = "According to Canada Post the address you entered is missing important "
			+ "information. \<br\>\<b\>To correct this: <\/b\> please choose the correct address "
			+ "below or choose one of the options on the right";
		com.qas.MSG_200 = "Your address selection covers a range of addresses. Enter your exact details.";
		com.qas.MSG_REFINE = "Your address selection covers a range of addresses. Enter your exact details.";
		com.qas.MSG_REFINE_ERROR = "Invalid range. Please input another refinement number.";
		com.qas.MSG_INTERACTION = "According to Canada Post the address you entered may be incorrect. "
			+ "\<br\>\<b\>To correct this: <\/b\> please choose from one of the options below. ";
		com.qas.MSG_NONE = "A match for your address could not be found in the Canada Post database. "
			+ "Please choose one of the options below to proceed.";
		com.qas.WAIT_MESSAGE = "Validating address data ...";
		com.qas.LINEONE = "Address&nbsp;1";
		com.qas.LINETWO = "Address&nbsp;2";
		com.qas.LINETHREE = "Address&nbsp;3";
		com.qas.CITY = "City";
		com.qas.STATE = "Province";
		com.qas.ZIP = "Postal Code";
	}
	else if (com.qas.COUNTRYSET == "USA") 
	{
		com.qas.MSG_PREMPARTIAL = "According to the USPS&#174; the address you entered is missing important "
			+ "information.\<br\>\<b\>To correct this: <\/b\> please enter the missing "
			+ "information in the box below or choose one of the options on the right.";
		com.qas.MSG_PREMPARTIAL_ERROR = "The secondary number you entered could not be found. Please refer "
			+ "to list of options below.";
		com.qas.MSG_STREETPARTIAL = "According to the USPS&#174; the street number you entered is either missing "
			+ "or incorrect. \<br\>\<b\>To correct this: <\/b\> please enter the street number in the box below or "
			+ "choose one of the options on the right to proceed.";
		com.qas.MSG_STREETPARTIAL_ERROR = "The street number you entered could not be found. Please refer "
			+ "to list of options below.";
		com.qas.MSG_MULITPLE = "According to the USPS® the address you entered is missing important "
			+ "information. \<br\>\<b\>To correct this: <\/b\> please choose the correct address "
			+ "below or choose one of the options on the right";
		com.qas.MSG_REFINE = "Your address selection covers a range of addresses. Enter your exact details.";
		com.qas.MSG_REFINE_FOUR = "Your address selection covers a range of ZIP+4's. Enter the exact +4 code required.";
		com.qas.MSG_REFINE_ERROR = "Invalid range. Please input another refinement number.";
		com.qas.MSG_INTERACTION = "According to the USPS&#174; the address you entered may be incorrect or incomplete. "
			+ "\<br\>\<b\>To correct this: <\/b\> please choose from one of the options below. ";
		com.qas.MSG_NONE = "A match for your address could not be found in the USPS database. "
			+ "Please choose one of the options below to proceed.";
		com.qas.WAIT_MESSAGE = promptMsg;
		com.qas.LINEONE = "Address&nbsp;1";
		com.qas.LINETWO = "Address&nbsp;2";
		com.qas.LINETHREE = "Address&nbsp;3";
		com.qas.CITY = "City";
		com.qas.STATE = "State";
		com.qas.ZIP = "Postal&nbsp;Code";
	}
	else
	{
				com.qas.MSG_PREMPARTIAL = "According to the local postal authority the address you entered is missing important "
			+ "information.\<br\>\<b\>To correct this: <\/b\> please enter the missing "
			+ "information in the box below or choose one of the options on the right.";
		com.qas.MSG_PREMPARTIAL_ERROR = "The secondary number you entered could not be found. Please refer "
			+ "to list of options below.";
		com.qas.MSG_STREETPARTIAL = "According to the local postal authority the street number you entered is either missing "
			+ "or incorrect. \<br\>\<b\>To correct this: <\/b\> please enter the street number in the box below or "
			+ "choose one of the options on the right to proceed.";
		com.qas.MSG_STREETPARTIAL_ERROR = "The street number you entered could not be found. Please refer "
			+ "to list of options below.";
		com.qas.MSG_MULITPLE = "According to the local postal authority the address you entered is missing important "
			+ "information. \<br\>\<b\>To correct this: <\/b\> please choose the correct address "
			+ "below or choose one of the options on the right";
		com.qas.MSG_REFINE = "Your address selection covers a range of addresses. Enter your exact details.";
		com.qas.MSG_REFINE_FOUR = "Your address selection covers a range of ZIP+4's. Enter the exact +4 code required.";
		com.qas.MSG_REFINE_ERROR = "Invalid range. Please input another refinement number.";
		com.qas.MSG_INTERACTION = "According to the local postal authority the address you entered may be incorrect. "
			+ "\<br\>\<b\>To correct this: <\/b\> please choose from one of the options below. ";
		com.qas.MSG_NONE = "A match for your address could not be found in the USPS database. "
			+ "Please choose one of the options below to proceed.";
		com.qas.WAIT_MESSAGE = promptMsg;
		com.qas.LINEONE = "Address&nbsp;1";
		com.qas.LINETWO = "Address&nbsp;2";
		com.qas.LINETHREE = "Address&nbsp;3";
		com.qas.CITY = "Town";
		com.qas.STATE = "Province";
		com.qas.ZIP = "Postal code";
	}
}

// Variable to hold the address that was originally entered
var originaladdress;

// Variable to hold the orginal third party button click events
existing_button_onclick = "";

// Set the state of the seach (initally false)
is_verified = false;

// Hold the verify level as a global var so that it can be referred to as the last action
current_widget = "";

// Variable to hold the last verify level
verify_level = "";

// Variable to hold the current search moniker (for refine prompting)
var current_moniker ="";

// Variable to count tries to the server
number_of_connection_attempts = 0;

//variable to tell if interaction has been accepted
var interaction_verified = "";

/**************************************************************************************************
* Constructor for the com.qas.ContentLoader object. This handles all interaction with the server
* and ensures that the return codes are correctly handled.
* @param url The url for the server call
* @param onload The name of the method in the event of success
* @param onerror The name of the method to call in the event of failure
* @param method Http submit method (get/ post)
* @param params An array of parameters to send
* @param contentType The http requeest content type
**************************************************************************************************/
com.qas.ContentLoader = function(onLoad, onError, method, params, contentType)
{
	this.req = null;
	this.onLoad = onLoad;
	this.onError = (onError) ? onError : this.defaultError;
	this.url = com.qas.AJAXURL;
	this.loadXMLDoc(method, params, contentType);
}

com.qas.ContentLoader.prototype = 
{
	/**
	* Private method to make the http request and call the specified onLoad/ onError as
	* appropriate (also sets the content type).
	*/
	loadXMLDoc:function(method, params, contentType)
	{
		// Parameters to store the last method call to handle re-submits		
		this.last_method = method;
		this.last_params = params;		
		this.last_content = contentType;
		
		if (! method)
		{
			method = "GET";
		}		
		if (! contentType && method == "POST")
		{
			contentType = "application/x-www-form-urlencoded";
		}		
		if (window.XMLHttpRequest)
		{
			this.req = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			this.req = new ActiveXObject("Microsoft.XMLHTTP");
		}
		if (this.req)
		{
			try
			{
				var loader = this;
				this.req.onreadystatechange = function()
				{
					loader.onReadyState.call(loader);
				}
				this.req.open(method, this.url, true);
				
				if (contentType)
				{
					this.req.setRequestHeader("Content-Type", contentType);
				}
				this.req.send(encodeURI(params));
			}
			catch (err)
			{			    
				this.onError.call(this);
			}
		}
	},
	
	/**
	* Method deals with the return from the server and makes the appropriate call as specified
	*/
	onReadyState:function()
	{
		var req = this.req;
		var ready = req.readyState;
		
		
		if (ready == com.qas.READY_STATE_COMPLETE)
		{
			var httpStatus = req.status;
			if (httpStatus == 200 || httpStatus == 0)
			{
				this.onLoad.call(this);
			}
			else
			{
				if (number_of_connection_attempts < com.qas.MAXIMUM_CONNECTION_ATTEMPTS)
				{
					number_of_connection_attempts++;
					this.loadXMLDoc(this.last_method, this.last_params, this.last_content);
				}
				else
				{
					this.onError.call(this);
				}
			}
		}
	},
	
	/**
	* The default error message, where no other error method is specified
	*/
	defaultError:function()
	{
		alert("An error has occurred. Please check the settings in the "
			+ "file proweb.htm and ensure that the server is running correctly");
	}
};

/**************************************************************************************************
* Simple class for managing parameters. Users pass parameters to the class via the addParameter
* method, and then access the correctly formatted string from toString(). No arg constructor.
**************************************************************************************************/
com.qas.AjaxParameters = function()
{
	this.parameter_string = "";
}

com.qas.AjaxParameters.prototype =
{
	/**
	* Adds a name/ value pair (both sent as strings)
	*/
	addParameter:function(name, value)
	{
		this.parameter_string = this.parameter_string + 
			name + "=" + value + "&";
	},
	
	/**
	* Returns all of the parameters as a formatted string ready for HTTP
	*/
	toString:function()
	{
		return this.parameter_string.slice(0, this.parameter_string.length - 1);
	}
}

/**************************************************************************************************
* A simple datatype class for holding address information. This contains only getters (all setting
* is done via the constructor) but provides a standard format for encapsulation. The constrcutor has:
* @param Address Line One
* @param Address Line Two
* @param Address Line Three
* @param Address City
* @param Address State
* @param Address Zip
New addition:  isApartment boolean to distinguish apartments
*@param Apartment 
**************************************************************************************************/
com.qas.Address = function(lineone, linetwo, linethree, city, state, zip, apartment)
{
	this.lineone = lineone;
	this.linetwo = linetwo;
	this.linethree = linethree;
	this.city = city;
	this.state = state;
	this.zip = zip;
	this.apartment = apartment;
}

com.qas.Address.prototype = 
{
	getLineOne:function()
	{
		return this.lineone;
	},
	
	getLineTwo:function()
	{
		return this.linetwo;
	},
	
	getLineThree:function()
	{
		return this.linethree;
	},
	
	getCity:function()
	{
		return this.city;
	},
	
	getState:function()
	{
		return this.state;
	},
	
	getZip:function()
	{
		return this.zip;
	},
	isApartment:function()
	{
		return this.apartment;
	}
}

/**************************************************************************************************
* A simple datatype class for holding multiple information. Simplar to the address class above,
* all setting is done through the constructor - only getters are available methods. Constrcutor has:
* @param Address Text
* @param Postcode
* @param Moniker
* @param Whether this is a full address or not
* @param Score
**************************************************************************************************/
com.qas.PartialResult = function(addresstext, postcode, moniker, is_full_address, score, is_unresolvablerange)
{
	this.addresstext = addresstext;
	this.postcode = postcode;
	this.moniker = moniker;
	this.is_full_address = is_full_address;
	this.score = score;
	this.is_unresolvablerange = is_unresolvablerange;
}

com.qas.PartialResult.prototype = 
{
	getAddressText:function()
	{
		return this.addresstext;
	},
	
	getPostcode:function()
	{
		return this.postcode;
	},
	
	getMoniker:function()
	{
		return this.moniker;
	},
		
	getScore:function()
	{
		return this.score;
	},
	
	isFullAddress:function()
	{
		return this.is_full_address;
	},
	
	isUnresolvableRange:function()
	{
		return this.is_unresolvablerange;
	}
}

/**************************************************************************************************
* This is the main point of interaction with the server. All searches are made through this class.
* Users are able to perform a standard search, a refine or a format of the information. The class
* has no state. The constructor has:
* @param The function to call on a successful HTTP call
* @param The function to call in the event of an error
**************************************************************************************************/
com.qas.SearchService = function(onLoad, onError) 
{
	this.onLoad = onLoad;
	this.onError = onError; 
}

com.qas.SearchService.prototype = 
{
	search:function(lone, ltwo, lthree, city, state, zip)
	{
	
		// Create the parameters to send
		var params = new com.qas.AjaxParameters();
		params.addParameter("action", "search");		
		params.addParameter("country", com.qas.COUNTRYSET);
		params.addParameter("promptset", com.qas.PROMPTSET);
		params.addParameter("addlayout", com.qas.ADDRESSLAYOUT);
		params.addParameter("searchstring", events.CanURLFunction(lone) + "|" + ltwo + "|" + 
			lthree + "|" + city + "|" + state + "|" + zip);
			//lthree + "," + city + "," + state + "," + zip);
		
		var loader = new com.qas.ContentLoader(this.onLoad, this.onError, "POST", params);
	},

	refine:function(moniker, refinetext)
	{
		// Create the parameters to send
		var params = new com.qas.AjaxParameters();
		
			params.addParameter("action", "refine");
		
		params.addParameter("moniker", moniker);
		params.addParameter("refinetext", refinetext);
		params.addParameter("addlayout", com.qas.ADDRESSLAYOUT);
		
		var loader = new com.qas.ContentLoader(this.onLoad, this.onError, "POST", params);
	},
	
	format:function(moniker)
	{
		// Create the parameters to send
		var params = new com.qas.AjaxParameters();
		params.addParameter("action", "format");
		params.addParameter("addlayout", com.qas.ADDRESSLAYOUT);
		params.addParameter("moniker", moniker);
		
		var loader = new com.qas.ContentLoader(this.onLoad, this.onError, "POST", params);
	}
};

/**************************************************************************************************
* Functions that implement business logic. All of them have the "business" prefix. However, they 
* are NOT objects as understood above, but rather just a collection of functions.
**************************************************************************************************/

/**************************************************************************************************
* Processes the search results - in almost all situations when a search is performed this is called
* on success as a central decision/ logic point. What to do is dependent of the verify level that
* is returned by the QAS engine.
**************************************************************************************************/
business.processSearchResults = function(interaction)
{
	
	var previous_verify_level = verify_level;
	var previous_moniker = current_moniker;
	
	
	verify_level = this.req.responseXML.getElementsByTagName
		("verifylevel")[0].firstChild.nodeValue;
	//alert("verify_level=" + verify_level);
	if (interaction_verified == true){verify_level = "Verified";}
	
	if (verify_level == "InteractionRequired" && previous_verify_level == "PremisesPartial")
	{
		verify_level = "Verified";
	}
 
	if (verify_level == "InteractionRequired" && previous_verify_level == "StreetPartial")
	{
		verify_level = "Verified";
	}
 
	if (verify_level == "InteractionRequired")
	{
		var interResult = business.parseSingleResult(this.req);
		if (events.checkForBldg(interResult.getLineOne()) == true)
		{
			verify_level = "Verified";
		} 
	}
 
	
	//  Check for a multiple result with unresolvable ranges - need to prompt for street number
		var j = 0;
        var i = 0;

    if (verify_level == "Multiple")
    {
        var tempresults = business.parsePicklistResults(this.req);
        for (i=0;i<tempresults.length;i++)
        {
                //alert(tempresults[i].isUnresolvableRange() + "\n\ri =" + i + "\n\rj=" + j);
            if (tempresults[i].isUnresolvableRange().toLowerCase() == "true") {j++;}
		}
        if (j > 0) { verify_level = "StreetPartial"; }
    }

	//  Check for a partial result with resolvable ranges (no picklist necessary)
		//var j = 0;
        //v/ar i = 0;

    //    if (verify_level == "PremisesPartial" || verify_level == "StreetPartial")
      //  {
        //    var tempresults = business.parsePicklistResults(this.req);
          //  for (i=0;i<tempresults.length;i++)
            //{
                //alert(tempresults[i].isUnresolvableRange() + "\n\ri =" + i + "\n\rj=" + j);
              //  if (tempresults[i].isUnresolvableRange() == "False") {j++;}
            //}
             //   if (j == tempresults.length) { verify_level = "Multiple"; }
        //}

	switch (verify_level)
	{
		case "PremisesPartial":
			var results = business.parsePicklistResults(this.req);
			// If the result is single, force an interaction
			if (results[0].isFullAddress().toLowerCase() == "true")
			{
				if (results.length == 1)
				{
					var sservice = new com.qas.SearchService(
						business.processForcedInteraction,
						business.processSearchError);
					sservice.refine(results[0].getMoniker(),"");
					return;
				}
				// Special case - proweb occasionally returns a verified address with    ***This Code is addressed above with the single premise***
				// more than one result?? This handles that situation.   **this code would cause issues in specific refinement cases because the verify levels weren't changing
				//else if (previous_verify_level == verify_level)
				//{
				//	var sservice = new com.qas.SearchService(
				//		business.processSearchResults,
				//		business.processSearchError);
				//	sservice.refine(results[0].getMoniker(),"");
				//	return;
				//}
			}
			
			if (previous_verify_level == verify_level && results.length > 1)
			{
				interface.showPremPartialError();
				return;
			}
			interface.showPremPartialResults(business.parsePicklistResults(this.req));
			
			//  Check for a refine error and display message
			current_moniker = results[0].getMoniker();
			if (previous_moniker == current_moniker)
			{
				interface.showRefineError();
			}
			
			break;
		case "StreetPartial":
			var results = business.parsePicklistResults(this.req);
			// If the result is single, force an interaction
			if (results.length == 1 && results[0].isFullAddress().toLowerCase() == "true")
			{
				var sservice = new com.qas.SearchService(
					business.processForcedInteraction,
					business.processSearchError);
				sservice.refine(results[0].getMoniker(),"");
				return;
			}
			if (previous_verify_level == verify_level && results.length > 1)
			{
				interface.showStreetPartialError();
				return;
			}
			interface.showStreetPartialResults(business.parsePicklistResults(this.req));
			break;
		case "Verified":
			is_verified = true;
			interface.showVerifiedResults(business.parseSingleResult(this.req));
			interface.appendApt(business.parseSingleResult(this.req));
			events.handleThirdPartyButtonClick();
			interaction_verified = "";
			break;
		case "InteractionRequired":
			interface.showInteractionResults(business.parseSingleResult(this.req));
			break;
		case "Multiple":
			interface.showMultipleResults(business.parsePicklistResults(this.req));
			break;
		case "None":
			if (com.qas.IGNORE_UNMATCHED_ADDRESSES.toLowerCase() == "true")
			{
				interface.showVerifiedResults(originaladdress);
				events.submitForm();			
			}
			else
			{
				interface.showNoResults();
			}
			break;
		default : 
			break;
	}
}

/**************************************************************************************************
* This takes the XML result from the HTTP call and wraps it in an array of  partial classes .
**************************************************************************************************/
business.parsePicklistResults = function(req)
{
	var results = new Array();
	var picklistitems = req.responseXML.getElementsByTagName("picklistitem");
	for (var i = 0; i < picklistitems.length; i++)
	{
		prempartial = new com.qas.PartialResult(
			picklistitems[i].getElementsByTagName("addresstext")[0].firstChild.nodeValue,
			(picklistitems[i].getElementsByTagName("postcode")[0].firstChild != null) ? picklistitems[i].getElementsByTagName("postcode")[0].firstChild.nodeValue : "",
			picklistitems[i].getElementsByTagName("moniker")[0].firstChild.nodeValue,
			picklistitems[i].getElementsByTagName("fulladdress")[0].firstChild.nodeValue,
			picklistitems[i].getElementsByTagName("score")[0].firstChild.nodeValue,
			picklistitems[i].getElementsByTagName("unresolvablerange")[0].firstChild.nodeValue);
		results[i] = prempartial;
	}
	return results;
}

/**************************************************************************************************
* This takes the XML result from the HTTP and wraps it in an address class.
(req.responseXML.getElementsByTagName("linetwo")[0].firstChild != null) ? req.responseXML.getElementsByTagName("linetwo")[0].firstChild.nodeValue : "",
**************************************************************************************************/

business.parseSingleResult = function(req)
{
var sAdd1 = "";
if (req.responseXML.getElementsByTagName("lineone")[0].firstChild != null) { sAdd1 = req.responseXML.getElementsByTagName("lineone")[0].firstChild.nodeValue;}
var sAdd2 = "";
if (req.responseXML.getElementsByTagName("linetwo")[0].firstChild != null) { sAdd2 = req.responseXML.getElementsByTagName("linetwo")[0].firstChild.nodeValue;}
var sAdd3 = "";
if (req.responseXML.getElementsByTagName("linethree")[0].firstChild != null) { sAdd3 = req.responseXML.getElementsByTagName("linethree")[0].firstChild.nodeValue;}
var sCity = "";
if (req.responseXML.getElementsByTagName("city")[0].firstChild != null) { sCity = req.responseXML.getElementsByTagName("city")[0].firstChild.nodeValue; }
var sState = "";
if (req.responseXML.getElementsByTagName("state")[0].firstChild != null) { sState = req.responseXML.getElementsByTagName("state")[0].firstChild.nodeValue; }
var sZIP = "";
if (req.responseXML.getElementsByTagName("zip")[0].firstChild != null) { sZIP = req.responseXML.getElementsByTagName("zip")[0].firstChild.nodeValue;}
var sApt = "";
if (req.responseXML.getElementsByTagName("apartment")[0].firstChild != null) { sApt = req.responseXML.getElementsByTagName("apartment")[0].firstChild.nodeValue;}

	if (sAdd1 == "")
	{
		sAdd1 = sAdd2;
		sAdd2 = sAdd3;
		if (sAdd1 == "" && sAdd2 != "")
		{
			sAdd1 = sAdd2;
			sAdd2 = "";
			
		}
	}
	if (sAdd2 == "" && sAdd3 != "")
	{
		sAdd2 = sAdd3;
		sAdd3 = "";
	}

	return new com.qas.Address(sAdd1, sAdd2, sAdd3, sCity, sState, sZIP, sApt);

	//return new com.qas.Address(
	//	(req.responseXML.getElementsByTagName("lineone")[0].firstChild != null) ? req.responseXML.getElementsByTagName("lineone")[0].firstChild.nodeValue : "", 
	//	(req.responseXML.getElementsByTagName("linetwo")[0].firstChild != null) ? req.responseXML.getElementsByTagName("linetwo")[0].firstChild.nodeValue : "",
	//	(req.responseXML.getElementsByTagName("linethree")[0].firstChild != null) ?	req.responseXML.getElementsByTagName("linethree")[0].firstChild.nodeValue : "",
	//	(req.responseXML.getElementsByTagName("city")[0].firstChild != null) ?	req.responseXML.getElementsByTagName("city")[0].firstChild.nodeValue : "",
	//	(req.responseXML.getElementsByTagName("state")[0].firstChild != null) ?	req.responseXML.getElementsByTagName("state")[0].firstChild.nodeValue : "",
	//	(req.responseXML.getElementsByTagName("zip")[0].firstChild != null) ? req.responseXML.getElementsByTagName("zip")[0].firstChild.nodeValue : "",
	//	(req.responseXML.getElementsByTagName("apartment")[0].firstChild != null) ?	req.responseXML.getElementsByTagName("apartment")[0].firstChild.nodeValue : "");
}

/**************************************************************************************************
* If the result is a single record premesis partial or a street partial, then display the record
* as an interaction required.
**************************************************************************************************/
business.processForcedInteraction = function()
{
	interface.showInteractionResults(business.parseSingleResult(this.req));
}

/**************************************************************************************************
* Standard method for handling a search error. Note that if the user has chosen to ignore this
* error (by setting IGNORE_CONNECTION_ERROR, then the method simply submits the form.
**************************************************************************************************/
business.processSearchError = function()
{
	if (com.qas.IGNORE_CONNECTION_ERROR.toLowerCase() == "true")
	{
		document.getElementById(com.qas.FORM_BUTTON_ID).onclick =
			function() { return true; };
		document.getElementById(com.qas.FORM_BUTTON_ID).click();
		document.forms[0].submit();
	}
	else
	{
		alert("An error has occurred. Please check the settings in the "
			+ "file proweb.htm and ensure that the server is running correctly (you "
			+ "can run test_server_setup to check.");
			
		document.body.removeChild(document.getElementById("wait_wgt"));
		document.getElementById("cover_wgt").style.display = "none";
	}
}

/**************************************************************************************************
* If the user has entered an incorrect refine range, this method is called.
**************************************************************************************************/
business.processRefineError = function()
{
	interface.showRefineError();
}

/**************************************************************************************************
* This method decides which button to display (if the user has specified a form button on the
* html).
**************************************************************************************************/
business.selectInputButton = function()
{
	if (com.qas.FORM_BUTTON_ID.length > 0)
	{
		var button = document.getElementById(com.qas.FORM_BUTTON_ID)
		if (button == null)
		{
			alert("Configuration: the specified button '" 
				+ com.qas.FORM_BUTTON_ID 
				+ "' does not exist.");
			return;
		}
		//document.getElementById("input_search").style.display = "none";
		
		if (button.getAttribute("onclick") != null)
		{
			existing_button_onclick = button.getAttribute("onclick");
		}
		button.onclick = events.handleThirdPartyButtonClick;
	}
}

/**************************************************************************************************
* All event handling methods. Events is not an class, simply a collection of functions.
**************************************************************************************************/

/**************************************************************************************************
* When the original form button is clicked to start the verification/ form submission. This starts
* a basic search with the values in the text input fields.
**************************************************************************************************/
events.handleClickInputButton = function(evt)
{    
	
	events.setMessages();
	
	// Display the cover widget to disable the page
	if (com.qas.RUN_AS_POPUP == "true")
	{
		// WE DON'T NEED TO SCROLL TO THE TOP BECAUSE WE ARE USING FUNCTIONS IN THE VIEWPORT JS FILE THAT AUTOMATICALLY
		// ALIGN THE OVERLAYS IN THE CENTER OF THE SCREEN TAKING INTO CONSIDERATION THE BROWSER SIZE AND THE CURRENT
		// SCROLL POSITION
		//window.scrollTo(0,0);
		interface.showCoverWidget();
		interface.displayWaitingWidget();
	}
	
	var lone = document.getElementById(LINEONECTL).value;
	var ltwo = document.getElementById(LINETWOCTL).value;
	var lthree = document.getElementById(LINETHREECTL).value;
	var city = document.getElementById(CITYCTL).value;
	var state = document.getElementById(STATECTL).value;
	var zip = document.getElementById(ZIPCTL).value;
	var country = document.getElementById(COUNTRYCTL).value;
	
	originaladdress = new com.qas.Address(lone, ltwo, lthree, city, state, zip);
	
	var sservice = new com.qas.SearchService(
		business.processSearchResults,
		business.processSearchError);
	
	sservice.search(lone, ltwo, lthree, city, state, zip);	
}

/**************************************************************************************************
* When the refine button is clicked from the refine widget
**************************************************************************************************/
events.handleClickRefineButton = function(evt)
{
	if (document.getElementById("refine_input").value.length <= 0)
	{
		alert("Please enter refinement text");
		return;
	}
	
	var sservice = new com.qas.SearchService(
		business.processSearchResults,
		business.processRefineError);
	sservice.refine(
		document.getElementById("refine_moniker").value,
		document.getElementById("refine_input").value);
}

/**************************************************************************************************
* Event called when a multiple result link is clicked (forces a refine of the result)
**************************************************************************************************/
events.handleClickMultipleButton = function(evt)
{
	var sservice = new com.qas.SearchService(
		business.processSearchResults,
		business.processSearchError);
	sservice.refine(this.getAttribute("moniker"), "");
}

/**************************************************************************************************
* Event called when the premises partial button is clicked (starts a search with an "apt" appendage)
**************************************************************************************************/
events.handleClickPremPartialButton = function(evt)
{
	var lone = document.getElementById(LINEONECTL).value + " apt " + 
		document.getElementById("partial_input").value;
	var ltwo = document.getElementById(LINETWOCTL).value;
	var lthree = document.getElementById(LINETHREECTL).value;
	var city = document.getElementById(CITYCTL).value;
	var state = document.getElementById(STATECTL).value;
	var zip = document.getElementById(ZIPCTL).value;
	var sservice = new com.qas.SearchService(
		business.processSearchResults,
		business.processSearchError);
	sservice.search(lone, ltwo, lthree, city, state, zip);
}

/**************************************************************************************************
* Event called when the street partial button is clicked (deals with urbanizations amongsth others)
**************************************************************************************************/
events.handleClickStreetPartialButton = function(evt)
{
	var lone = document.getElementById(LINEONECTL).value;
	var ltwo = document.getElementById(LINETWOCTL).value;
	
	var urbregex = new RegExp("^(urb|urbanisation|urbanización)", "i");
	if (urbregex.exec(document.getElementById(LINEONECTL).value) != null)
	{
		ltwo = document.getElementById("partial_input").value + " " + ltwo;
		document.getElementById(LINETWOCTL).value = ltwo;
	}
	else
	{
		lone = document.getElementById("partial_input").value + " " 
			+ lone.replace(/^[0-9]+/,"");
		document.getElementById("LINEONECTL").value = lone;
	}
	
	var lthree = document.getElementById(LINETHREECTL).value;
	var city = document.getElementById(CITYCTL).value;
	var state = document.getElementById(STATECTL).value;
	var zip = document.getElementById(ZIPCTL).value;
	var sservice = new com.qas.SearchService(
		business.processSearchResults,
		business.processSearchError);
	sservice.search(lone, ltwo, lthree, city, state, zip);
}

/**************************************************************************************************
* Event called when links from either prem or street partial results are clicked (calls refine)
**************************************************************************************************/
events.handleClickPartialText = function(evt)
{
	var sservice = new com.qas.SearchService(
		business.processSearchResults,
		business.processSearchError);
		
	sservice.refine(this.getAttribute("moniker"), "");
}

/**************************************************************************************************
* Event called when button clicked from the interaction widget
**************************************************************************************************/
events.handleClickInteractionButton = function(evt)
{
	if(document.getElementById("interaction_apt").value == "True")
	{
		interaction_verified = true;
	
		var lone = document.getElementById("interaction_lineone").innerHTML;
		var ltwo = document.getElementById("interaction_linetwo").innerHTML;
		var lthree = document.getElementById("interaction_linethree").innerHTML;
		var city = document.getElementById("interaction_linecity").innerHTML;
		var state = document.getElementById("interaction_linestate").innerHTML;
		var zip = document.getElementById("interaction_linezip").innerHTML;
		
		originaladdress = new com.qas.Address(lone, ltwo, lthree, city, state, zip);
		
		var sservice = new com.qas.SearchService(
			business.processSearchResults,
			business.processSearchError);
		
		sservice.search(lone, ltwo, lthree, city, state, zip);
	}
	else
	{
		is_verified = true;
		interface.showVerifiedResults(new com.qas.Address(
			document.getElementById("interaction_lineone").innerHTML,
			document.getElementById("interaction_linetwo").innerHTML,
			document.getElementById("interaction_linethree").innerHTML,
			document.getElementById("interaction_linecity").innerHTML,
			document.getElementById("interaction_linestate").innerHTML,
			document.getElementById("interaction_linezip").innerHTML));
		events.handleThirdPartyButtonClick();
	}
}

/**************************************************************************************************
* Event called when the users click to view partial results (displays them)
**************************************************************************************************/
events.handleClickShowPartialResults = function(evt)
{
	document.getElementById("partial_showlink").innerHTML = "";
	document.getElementById("partial_allresults").style.display = "";
}

/**************************************************************************************************
* Event when the users click "choose this address" from the right hand details widget.
**************************************************************************************************/
events.handleChooseAddressText = function(evt)
{
	verify_level = "none";
	interface.clearNonVerifiedWidgets();
	interface.showVerifiedResults(originaladdress);
	// THE LINE BELOW LOOKS GREAT, BUT THIS IS THE ONLY REFERENCE TO COM.QAS.BYPASS_QAS_VERIFICATION IN THIS FILE.
	//com.qas.BYPASS_QAS_VERIFICATION = true;
	document.getElementById("BYPASS_QAS_VERIFICATION").value = true;
	events.submitForm();
}

/**************************************************************************************************
* Event when the user clicks "edit this address" from the right hand details widget.
**************************************************************************************************/
events.handleEditAddressText = function(evt)
{
	verify_level = "";
	current_moniker = "";
	interface.clearNonVerifiedWidgets();
	interface.showAddressInput(originaladdress);
	document.getElementById("wait_wgt").style.display = "none";
}

/**************************************************************************************************
* This function actually is a response to any event wanting to submit the form in question. It is 
* required as well as the function below because users may wish to ignore unmatched addresses.
**************************************************************************************************/
events.submitForm = function(evt)
{
	// If we are not in a form, then do not do anything (there is no third party button)
	if (com.qas.FORM_BUTTON_ID.length <= 0 || document.getElementById(com.qas.FORM_BUTTON_ID) == null)
	{
		return;
	}

	document.getElementById(com.qas.FORM_BUTTON_ID).onclick =
		function() { return true; };
	document.getElementById(com.qas.FORM_BUTTON_ID).click();
}

/**************************************************************************************************
* When the user click the form button, this method decides what to do. It first runs any javascript
* already associated with the button click event. Once that has run successfully (returned true)
* then it runs the address verification. If it happy that the address is verified (or that the user
* does not want to verify), then it submit the form.
**************************************************************************************************/
events.handleThirdPartyButtonClick = function(evt)
{
	// If we are not in a form, then do not do anything (there is no third party button)
	if (com.qas.FORM_BUTTON_ID.length <= 0 || document.getElementById(com.qas.FORM_BUTTON_ID) == null)
	{
		return;
	}
	
	// If an error should be ignored, submit the form anyway
	if ((com.qas.IGNORE_CONNECTION_ERROR.toLowerCase() == "true")
	&& (verify_level.toLowerCase() == "none"))
	{
		document.getElementById(com.qas.FORM_BUTTON_ID).onclick = existing_button_onclick; 
		document.getElementById(com.qas.FORM_BUTTON_ID).click();
	}

	// If we are on the first page, run the inital javascript for the page. If that 
	// completes, run the QAS code
	if ((current_widget == "input_wgt") && (is_verified != true))
	{
		// Run the existing code for the onclick event, but catch the return
		var return_button;
		try 
		{ 
			return_value = existing_button_onclick(); 
		}
		catch(err) 
		{ 
			return_value = eval(existing_button_onclick.replace(/(^|;| )return /i, "")); 
		}
		
		if (return_value == true || return_value == null)
		{
			// If the user has chosen to bypass qas, reset the button and click
			if (document.getElementById("BYPASS_QAS_VERIFICATION").value.toLowerCase() == "true")
			{
				return true; 
			}
	
			events.handleClickInputButton();
		}
		return false;
	}
	else if ((current_widget == "input_wgt") && (is_verified == true))
	{
		document.getElementById(com.qas.FORM_BUTTON_ID).click();
		return true;
	}
	else
	{
		//alert("You must select a valid address before you continue");
		return false;
	}
}

/**************************************************************************************************
* This event acts as a general onKeyPress event for those input boxes that submit a widget when
* the return key is pressed.
**************************************************************************************************/
events.handleSubmitOnEnterKey = function(evt)
{
	var button;
	if (current_widget == "refine_wgt")
	{
		button = document.getElementById("refine_btnsubmit");
	}
	else
	{
		button = document.getElementById("partial_btnsubmit");
	}
	
	// Deal with browser incompatibility
	if (window.event == null)
	{
		if (evt && evt.keyCode == 13) 
		{
			button.click();
		}
	}
	else
	{
		if (window.event && window.event.keyCode == 13) 
		{
			button.click();
		}
	}
}

/**************************************************************************************************
* As well as the above, this form ensures that, when return is pressed by the user, the document/ 
* form is not also submitted (i.e problem only)
**************************************************************************************************/
events.preventSubmissionFormEnter = function(evt)
{
	// Deal with browser incompatibility
	if (window.event == null)
	{
		return !(evt && evt.keyCode == 13); 
	}
	else
	{
		return !(window.event && window.event.keyCode == 13); 
	}
}
/**************************************************************************************************
*Check for "-" to determine if there is an apartment
**************************************************************************************************/
events.checkForApt = function(address)
{
	var bool = false;

	var linetwo = address.getLineTwo();

	for(var i=0; i<linetwo.length;i++)
	{
		if(linetwo.charAt(i) == "-"){bool=true;}
	}
	return bool;
}
/**************************************************************************************************
* Appends the apartment to the front of the address
*Test
**************************************************************************************************/
events.appendApt = function()
{
	var holder1 = document.getElementById(LINEONECTL).value;
	var holder2 = document.getElementById(LINETWOCTL).value;
	var apt = document.getElementById("apt_input").value;
	if (events.checkForBldg(holder1) == true)
	{
		document.getElementById(LINEONECTL).value = apt + "-" + holder2;
		document.getElementById(LINETWOCTL).value = "";
	}
	else
	{
		document.getElementById(LINETWOCTL).value = apt + "-" + holder2;
	}
	interface.selectDisplay("input_wgt");
	
}
/**************************************************************************************************
* handles if the user doesn't want to enter an apartment when suggested
*Test
**************************************************************************************************/
events.handleNoApt = function()
{
	var holder1 = document.getElementById(LINEONECTL).value;
	var holder2 = document.getElementById(LINETWOCTL).value;
	if (events.checkForBldg(holder1) == true)
	{
		document.getElementById(LINEONECTL).value = holder2;
		document.getElementById(LINETWOCTL).value = "";
	}
	interface.selectDisplay("input_wgt");
	// ADDED BY DAN ROUW 10/13/2010. WITHOUT THIS LINE THE QAS OVERLAY WILL JUST CLOSE WHEN
	// THE USER CLICKS THE LINK TO INDICATE THEY HAVE NO APARTMENT NUMBER. THEN THEY HAVE
	// TO CLICK THE FORM SUBMIT BUTTON AGAIN, WHICH DOESN'T SEEM RIGHT
	events.submitForm();
}
/**************************************************************************************************
*Check for a common building name to determine if there is an apartment
**************************************************************************************************/
events.checkForBldg = function(address)
{
	var bool = false;
	if (address == "Business") {bool = true;}
	if (address == "Building") {bool = true;}
	if (address == "Bldg") {bool = true;}
	if (address == "Business Bldg") {bool = true;}
	if (address == "Business Bldg.") {bool = true;}
	if (address == "Business Building") {bool = true;}
	if (address == "Business Complex") {bool = true;}
	if (address == "Business Plaza") {bool = true;}
	if (address == "Immeuble Commercial") {bool = true;}
	if (address == "Apt") {bool = true;}
	if (address == "Apartment") {bool = true;}
	if (address == "Apartment Bldg") {bool = true;}
	if (address == "Apartment Bldg.") {bool = true;}
	if (address == "Apartment Building") {bool = true;}
	if (address == "Immeuble a Appartements") {bool = true;}
	if (address == "Townhomes") {bool = true;}
	if (address == "Townhouses") {bool = true;}

	return bool;
}

events.CanURLFunction = function(sString)
{
	var sOutput="";
	sOutput = sString.replace(/&/gi, "%38");
	sOutput = sOutput.replace(/&amp;/gi, "%38");
	sOutput = sOutput.replace(/&frasl;/gi, "%47");
	sOutput = sOutput.replace(/¿/gi, "%191");
	sOutput = sOutput.replace(/À/gi, "%192"); 
	sOutput = sOutput.replace(/Á/gi, "%193");
	sOutput = sOutput.replace(/Â/gi, "%194"); 
	sOutput = sOutput.replace(/Ã/gi, "%195"); 
	sOutput = sOutput.replace(/Ä/gi, "%196"); 
	sOutput = sOutput.replace(/Å/gi, "%197"); 
	sOutput = sOutput.replace(/Æ/gi, "%198"); 
	sOutput = sOutput.replace(/Ç/gi, "%199"); 
	sOutput = sOutput.replace(/È/gi, "%200"); 
	sOutput = sOutput.replace(/É/gi, "%201"); 
	sOutput = sOutput.replace(/Ê/gi, "%202"); 
	sOutput = sOutput.replace(/Ë/gi, "%203"); 
	sOutput = sOutput.replace(/Ì/gi, "%204"); 
	sOutput = sOutput.replace(/Í/gi, "%205"); 
	sOutput = sOutput.replace(/Î/gi, "%206"); 
	sOutput = sOutput.replace(/Ï/gi, "%207"); 
	sOutput = sOutput.replace(/Ð/gi, "%208"); 
	sOutput = sOutput.replace(/Ñ/gi, "%209"); 
	sOutput = sOutput.replace(/Ò/gi, "%210"); 
	sOutput = sOutput.replace(/Ó/gi, "%211"); 
	sOutput = sOutput.replace(/Ô/gi, "%212"); 
	sOutput = sOutput.replace(/Õ/gi, "%213"); 
	sOutput = sOutput.replace(/Ö/gi, "%214"); 
	sOutput = sOutput.replace(/Ø/gi, "%216"); 
	sOutput = sOutput.replace(/Ú/gi, "%218"); 
	sOutput = sOutput.replace(/Û/gi, "%219"); 
	sOutput = sOutput.replace(/Ü/gi, "%220"); 
	sOutput = sOutput.replace(/Ý/gi, "%221"); 
	sOutput = sOutput.replace(/Þ/gi, "%222"); 
	sOutput = sOutput.replace(/ß/gi, "%223"); 
	sOutput = sOutput.replace(/à/gi, "%224"); 
	sOutput = sOutput.replace(/á/gi, "%225"); 
	sOutput = sOutput.replace(/â/gi, "%226"); 
	sOutput = sOutput.replace(/ã/gi, "%227"); 
	sOutput = sOutput.replace(/ä/gi, "%228"); 
	sOutput = sOutput.replace(/å/gi, "%229");
	sOutput = sOutput.replace(/æ/gi, "%230");
	sOutput = sOutput.replace(/ç/gi, "%231");
	sOutput = sOutput.replace(/è/gi, "%232");
	sOutput = sOutput.replace(/é/gi, "%233");
	sOutput = sOutput.replace(/ê/gi, "%234");
	sOutput = sOutput.replace(/ë/gi, "%235");
	sOutput = sOutput.replace(/ì/gi, "%236");
	sOutput = sOutput.replace(/í/gi, "%237");
	sOutput = sOutput.replace(/î/gi, "%238");
	sOutput = sOutput.replace(/ï/gi, "%239");
	sOutput = sOutput.replace(/ð/gi, "%240");
	sOutput = sOutput.replace(/ñ/gi, "%241");
	sOutput = sOutput.replace(/ò/gi, "%242");
	sOutput = sOutput.replace(/ó/gi, "%243");
	sOutput = sOutput.replace(/ô/gi, "%244");
	sOutput = sOutput.replace(/ô/gi, "%244");	
	sOutput = sOutput.replace(/õ/gi, "%245");
	sOutput = sOutput.replace(/ö/gi, "%246");
	sOutput = sOutput.replace(/ø/gi, "%248");
	sOutput = sOutput.replace(/ù/gi, "%249");
	sOutput = sOutput.replace(/ú/gi, "%250");
	sOutput = sOutput.replace(/û/gi, "%251");
	sOutput = sOutput.replace(/ü/gi, "%252");
	sOutput = sOutput.replace(/ý/gi, "%253");
	sOutput = sOutput.replace(/þ/gi, "%254");
	sOutput = sOutput.replace(/ÿ/gi, "%255");
	/*alert(sString + "\n\n'" + sOutput+"'");*/
	return sOutput;
}

/**************************************************************************************************
* Interface functions. interface is not a class, but simply a collection of presentation functions
**************************************************************************************************/

/**************************************************************************************************
*Added to prompt for apt if non is entered
*This will also deal with an apartment already being part of an address- it will remove the Building Name and add the apt to the first line
*comment out the else if to remove this functionality
*Test Only
**************************************************************************************************/
interface.appendApt = function(address)
{
	var holder2 = document.getElementById(LINEONECTL).value;
	if ((events.checkForApt(address) == false) && (address.isApartment().toLowerCase() == "true") && (com.qas.COUNTRYSET == "CAN"))
	{	
		document.getElementById("partial_wgt").innerHTML = "";
		
		var message = document.createElement("dt");
		message.innerHTML = "Canada Post has indicated your address may contain an apartment or suite."
							+ "\<br\>\<br\>\<b\>If you have an apartment or suite: <\/b\> please enter the number in the box below or choose one of the options on the right.";
				message.className = "qas_message";
		document.getElementById("partial_wgt").appendChild(message);
	
		interface.showRightDetails("partial_wgt");
		
		var label = document.createElement("label");
		label.innerHTML = "Apt/Ste (# only): ";
		document.getElementById("partial_wgt").appendChild(label);
		
		var input = document.createElement("input");
		input.setAttribute("type", "input");
		input.setAttribute("id", "apt_input");
		input.setAttribute("value", "");
		input.className = "qas_refinebutton";
		input.onkeypress = events.handleSubmitOnEnterKey;
		document.getElementById("partial_wgt").appendChild(input);
		
		var button = document.createElement("input");
		button.setAttribute("type", "button");
		button.setAttribute("id", "partial_btnsubmit");
		button.setAttribute("value", "Continue");
		button.className = "qas_refinebutton";
		button.onclick = events.appendApt;
		document.getElementById("partial_wgt").appendChild(button);
		
		var noapt = document.createElement("dt");
		noapt.className = "qas_link";
		noapt.innerHTML = "My address does not have an apartment or suite.";
		noapt.onclick = events.handleNoApt;
		//choosebutton.onclick = events.handleChooseAddressText;
		document.getElementById("partial_wgt").appendChild(noapt);
		
		interface.selectDisplay("partial_wgt");
		document.getElementById("apt_input").focus();


	}
	/*replaced checkforapt(address) with checkforbldg*/
	else if (events.checkForBldg(holder2) == true)
	{
		var holder = document.getElementById(LINETWOCTL).value;
		document.getElementById(LINEONECTL).value = holder;
		document.getElementById(LINETWOCTL).value = "";
	
	}
	
}
/**************************************************************************************************
* Displays the address in the original prompt input fields
**************************************************************************************************/
interface.showAddressInput = function(address)
{
	document.getElementById(LINEONECTL).value = address.getLineOne();
	document.getElementById(LINETWOCTL).value = address.getLineTwo();
	document.getElementById(LINETHREECTL).value = address.getLineThree();
	document.getElementById(CITYCTL).value = address.getCity();
	document.getElementById(STATECTL).value = address.getState();
	document.getElementById(ZIPCTL).value = address.getZip();
	interface.selectDisplay("input_wgt");
}

/**************************************************************************************************
* Display a fully verified result in the original input fields (or an unverified address if the
* setting is that the address need not be verified).
**************************************************************************************************/
interface.showVerifiedResults = function(address)
{
	// Remove all other HTML for the form submission
	interface.clearNonVerifiedWidgets();
	
	/*if (com.qas.FORM_BUTTON_ID.length <= 0)
	{
		document.getElementById("input_search").style.display = "none";
	}*/
	
	document.getElementById("QASMatched").value = is_verified;
	document.getElementById(LINEONECTL).value = address.getLineOne();
	document.getElementById(LINETWOCTL).value = address.getLineTwo();
	document.getElementById(LINETHREECTL).value = address.getLineThree();
	document.getElementById(CITYCTL).value = address.getCity();
	document.getElementById(STATECTL).value = address.getState();
	document.getElementById(ZIPCTL).value = address.getZip();
	interface.selectDisplay("input_wgt");
}

/**************************************************************************************************
* Displays all multiple results (as a list of links)
**************************************************************************************************/
interface.showMultipleResults = function(results)
{
	document.getElementById("multiple_wgt").innerHTML = "";
	
	var message = document.createElement("dt");
	message.innerHTML = com.qas.MSG_MULITPLE;
	message.className = "qas_message";
	document.getElementById("multiple_wgt").appendChild(message);
	
	interface.showRightDetails("multiple_wgt");
		
	var title = document.createElement("dt");
	title.innerHTML = "<BR>All potential missing information<BR><BR>";
	//title.className = "qas_title";
	document.getElementById("multiple_wgt").appendChild(title);
	
	for(var i = 0; i < results.length; i++)
	{
		result = document.createElement("dt");
		result.setAttribute("moniker", results[i].getMoniker());
		result.innerHTML = results[i].getAddressText() + 
			"<label class='qas_postcode'>" + results[i].getPostcode() + "</label>";
		//alert(results[i].isFullAddress());
		if (results[i].isFullAddress().toLowerCase() == "true")
		{
			result.className = "qas_link";
			result.onclick = events.handleClickMultipleButton;
		}
		else
		{
			result.className = "qas_range";
		}
		
		document.getElementById("multiple_wgt").appendChild(result);
	}
	interface.selectDisplay("multiple_wgt");
}

/**************************************************************************************************
* Show the premises partial results
**************************************************************************************************/
interface.showPremPartialResults = function(results)
{
	interface.showPartialResults(
		results, events.handleClickPremPartialButton, 
		com.qas.MSG_PREMPARTIAL, "Enter apartment/suite/unit number:");
}

/**************************************************************************************************
* Show the street partial results
**************************************************************************************************/
interface.showStreetPartialResults = function(results)
{
	interface.showPartialResults(
		results, events.handleClickStreetPartialButton, 
		com.qas.MSG_STREETPARTIAL, "Enter street number:");
}

/**************************************************************************************************
* because the partial (prem and street) share so much functionality, this function is used by both
* (the results, button event, main message and label message are sent as args)
**************************************************************************************************/
interface.showPartialResults = function(results, buttonevent, msg, label_msg)
{
	if (results.length == 1)
	{
		interface.showRefinePrompt(results[0]);
	}
	else
	{		
		document.getElementById("partial_wgt").innerHTML = "";
		
		var message = document.createElement("dt");
		message.innerHTML = msg;
		message.className = "qas_message";
		document.getElementById("partial_wgt").appendChild(message);
	
		interface.showRightDetails("partial_wgt");
		
		var h5 = document.createElement("h5");
		h5.innerHTML = "<h5>Suggested Address:</h5>";
		document.getElementById("partial_wgt").appendChild(h5);
		
		var label = document.createElement("label");
		label.innerHTML = label_msg + "&nbsp;&nbsp;";
		document.getElementById("partial_wgt").appendChild(label);
		
		var input = document.createElement("input");
		input.setAttribute("type", "input");
		input.setAttribute("id", "partial_input");
		input.setAttribute("value", "");
		input.className = "qas_refinebutton";
		input.onkeypress = events.handleSubmitOnEnterKey;
		document.getElementById("partial_wgt").appendChild(input);
		
		var button = document.createElement("input");
		button.setAttribute("type", "button");
		button.setAttribute("id", "partial_btnsubmit");
		button.setAttribute("value", "OK");
		button.className = "qas_acceptbutton";
		button.onclick = buttonevent;
		document.getElementById("partial_wgt").appendChild(button);
		
		var showlink = document.createElement("dt");
		showlink.className = "qas_link";
		showlink.setAttribute("id", "partial_showlink");
		showlink.innerHTML = "<br>Display all potential matches";
		showlink.onclick = events.handleClickShowPartialResults;
		document.getElementById("partial_wgt").appendChild(showlink);
		
		var resultholder = document.createElement("dd");
		resultholder.setAttribute("id", "partial_allresults");
		resultholder.style.display = "none";
		
		for(var i = 0; i < results.length; i++)
		{
			var result = document.createElement("dt");
			result.setAttribute("moniker", results[i].getMoniker());
			//result.className = "qas_link";
			result.innerHTML = results[i].getAddressText() + 
				"<label class='qas_postcode'>" + results[i].getPostcode() + "</label>";
			//result.onclick = events.handleClickPartialText;
			resultholder.appendChild(result);
			//alert(results[i].isFullAddress());
			if (results[i].isFullAddress().toLowerCase() == "true")
			{
				result.className = "qas_range";
				result.onclick = events.handleClickPartialText;
			}
			else
			{
				result.className = "qas_range";
			//result.onclick = events.handleClickPartialText;
			}
		}
		
		document.getElementById("partial_wgt").appendChild(resultholder);
		interface.selectDisplay("partial_wgt");
		document.getElementById("partial_input").focus();
	}
}

/**************************************************************************************************
* This shows an address that requires confirmation/ interaction
**************************************************************************************************/
interface.showInteractionResults = function(result)
{	
	document.getElementById("interaction_wgt").innerHTML = "";
	
	var message = document.createElement("dt");
	message.innerHTML = com.qas.MSG_INTERACTION;
	message.className = "qas_message";
	document.getElementById("interaction_wgt").appendChild(message);
	
	interface.showRightDetails("interaction_wgt");
	
	var h5 = document.createElement("h5");
	h5.innerHTML = "<h5>Suggested Address:</h5>";
	document.getElementById("interaction_wgt").appendChild(h5);
	
	/*var spacing = document.createElement("dt");
	spacing.innerHTML = "<BR>";
	document.getElementById("interaction_wgt").appendChild(spacing);*/
	var lone = document.createElement("dt");
	lone.setAttribute("id", "interaction_lineone");
	lone.innerHTML = result.getLineOne();
	document.getElementById("interaction_wgt").appendChild(lone);
	
	var ltwo = document.createElement("dt");
	ltwo.setAttribute("id", "interaction_linetwo");
	ltwo.innerHTML = result.getLineTwo();
	document.getElementById("interaction_wgt").appendChild(ltwo);
	
	var lthree = document.createElement("dt");
	lthree.setAttribute("id", "interaction_linethree");
	lthree.innerHTML = result.getLineThree();
	document.getElementById("interaction_wgt").appendChild(lthree);
	
	var lcity = document.createElement("dt");
	lcity.setAttribute("id", "interaction_linecity");
	lcity.innerHTML = result.getCity();
	document.getElementById("interaction_wgt").appendChild(lcity);
	
	var lstate = document.createElement("dt");
	lstate.setAttribute("id", "interaction_linestate");
	lstate.innerHTML = result.getState();
	document.getElementById("interaction_wgt").appendChild(lstate);
	
	var lzip = document.createElement("dt");
	lzip.setAttribute("id", "interaction_linezip");
	lzip.innerHTML = result.getZip();
	document.getElementById("interaction_wgt").appendChild(lzip);
	
	var lapt = document.createElement("input");
	lapt.setAttribute("type", "hidden");
	lapt.setAttribute("id", "interaction_apt");
	lapt.setAttribute("value", result.isApartment());
	document.getElementById("interaction_wgt").appendChild(lapt);
	 
	var button = document.createElement("input");
	button.setAttribute("type", "button");
	button.setAttribute("id", "partial_btnsubmit");
	button.setAttribute("value", "Select Address");
	button.className = "qas_acceptbutton";
	button.onclick = events.handleClickInteractionButton;
	document.getElementById("interaction_wgt").appendChild(button);
	
		
	interface.selectDisplay("interaction_wgt");
}

/**************************************************************************************************
* Displays the refine prompt widget
**************************************************************************************************/
interface.showRefinePrompt = function(result)
{	
	document.getElementById("refine_wgt").innerHTML = "";
	
	var message = document.createElement("dt");
	if (result.getPostcode().indexOf(".") != -1)
	{
		message.innerHTML = com.qas.MSG_REFINE_FOUR;
	}
	else
	{
		message.innerHTML = com.qas.MSG_REFINE;
	}
	message.className = "qas_message";
	document.getElementById("refine_wgt").appendChild(message);

	interface.showRightDetails("refine_wgt");
			
	var input = document.createElement("input");
	input.setAttribute("type", "input");
	input.setAttribute("id", "refine_input");
	input.setAttribute("value", "");
	input.className = "qas_refinebutton";
	input.onkeypress = events.handleSubmitOnEnterKey;
	document.getElementById("refine_wgt").appendChild(input);
	
	var hinput = document.createElement("input");
	hinput.setAttribute("type", "hidden");
	hinput.setAttribute("id", "refine_moniker");
	hinput.setAttribute("value", result.getMoniker());
	document.getElementById("refine_wgt").appendChild(hinput);
	
	var button = document.createElement("input");
	button.setAttribute("type", "button");
	button.setAttribute("id", "refine_btnsubmit");
	button.setAttribute("value", "OK");
	button.className = "qas_refinebutton";
	button.onclick = events.handleClickRefineButton
	document.getElementById("refine_wgt").appendChild(button);
	
	var addtext = document.createElement("dt");
	addtext.innerHTML = result.getAddressText();
	document.getElementById("refine_wgt").appendChild(addtext);
	
	interface.selectDisplay("refine_wgt");
	document.getElementById("refine_input").focus();
}

/**************************************************************************************************
* Thsi perfoms the logic as to which widget shoudl be displayed (this depends also on whether the
* user has chosen to run proweb as a pop-up or not).
**************************************************************************************************/
interface.selectDisplay = function(div_name)
{
	// If the user has chosen not to display pop-ups, simply display normally
	if (com.qas.RUN_AS_POPUP.toLowerCase() != "true")
	{
		interface.showSelectedDisplay(div_name);
		current_widget = div_name;
		return;
	}
	
	if (div_name == "input_wgt")
	{
		document.getElementById("cover_wgt").style.display = "none";
		interface.manageSelectFields("");
		//document.body.style.overflow = "visible";
		interface.showSelectedDisplay(div_name);
        document.getElementById("wait_wgt").style.display = "none";
	}
	else
	{
		//document.body.removeChild(document.getElementById("wait_wgt"));   //***will break code in IE6***//
		interface.showPopupDisplay(div_name);
		document.getElementById(div_name).style.display = "block";
		//document.body.style.overflow = "hidden";
		interface.manageSelectFields("none");
		interface.showCoverWidget();
	}
	current_widget = div_name;
}

/**************************************************************************************************
* Due to a bug in IE6, select boxes are not placed on the correct layer (they show through the
* cover div). This removes and then replaces them where appropriate.
**************************************************************************************************/
interface.manageSelectFields = function(display_type)
{
	var selects = document.body.getElementsByTagName("select");
	for (var i = 0; i < selects.length; i++)
	{
	    selects[i].style.display = display_type;
	}
	
}

/**************************************************************************************************
* Displays the background that disables the page
**************************************************************************************************/
interface.showCoverWidget = function()
{
	document.getElementById("cover_wgt").style.display = "block";
	// RESET THE SIZE OF THE COVER WIDGET DIV TO COVER THE ENTIRE SCREEN
	document.getElementById("cover_wgt").style.width = $Viewport.relativeWidth() + 'px';
	document.getElementById("cover_wgt").style.height = $Viewport.absoluteHeight() + 'px';
	
	//$Viewport.align("wait_wgt");
	
	// WE ARE NOT USING THE BODY OVERFLOW BECAUSE IT CAN CAUSE A SECOND SCROLL BAR DUE TO APPEAR ON THE PAGE
	/*if (document.body.style.overflow == "hidden") 
	{
		document.getElementById("cover_wgt").style.width = "100%";
		document.getElementById("cover_wgt").style.height = "100%";
	}*/
}	

/**************************************************************************************************
* Displays the waiting widget (in case the lookup takes a while)
**************************************************************************************************/
interface.displayWaitingWidget = function()
{
	// CENTER THE WAIT MESSAGE DIV IN THE BROWSER
	document.getElementById("wait_wgt").style.display = "block";
	$Viewport.align("wait_wgt");
}

/**************************************************************************************************
* Displays the pop-up div (if specified in the HTML)
**************************************************************************************************/
interface.showPopupDisplay = function(div_name)
{
	document.getElementById("multiple_wgt").style.display = "none";
	document.getElementById("partial_wgt").style.display = "none";
	document.getElementById("refine_wgt").style.display = "none";
	document.getElementById("interaction_wgt").style.display = "none";
	
	document.getElementById(div_name).style.display = "";
	
	// CENTER THE POPUP DIV IN THE BROWSER
	$Viewport.align(div_name);
}

/**************************************************************************************************
* Function displays the specified widget abnd hides all others
**************************************************************************************************/
interface.showSelectedDisplay = function(div_name)
{
	document.getElementById("input_wgt").style.display = "none";
	document.getElementById("multiple_wgt").style.display = "none";
	document.getElementById("partial_wgt").style.display = "none";
	document.getElementById("refine_wgt").style.display = "none";
	document.getElementById("interaction_wgt").style.display = "none";
	document.getElementById("none_wgt").style.display = "none";
	
	document.getElementById(div_name).style.display = "";
	
	// CENTER THE POPUP DIV IN THE BROWSER
	$Viewport.align(div_name);
}

/**************************************************************************************************
* This clears all of the widgets of their HTML (does not just hide them).
**************************************************************************************************/
interface.clearNonVerifiedWidgets = function()
{
	document.getElementById("multiple_wgt").innerHTML = "";
	document.getElementById("partial_wgt").innerHTML = "";
	document.getElementById("refine_wgt").innerHTML = "";
	document.getElementById("interaction_wgt").innerHTML = "";
	document.getElementById("none_wgt").innerHTML = "";
}

/**************************************************************************************************
* The error as shown when the refine range is incorrect
**************************************************************************************************/
interface.showRefineError = function()
{
	alert(com.qas.MSG_REFINE_ERROR);
	document.getElementById("refine_input").value = "";
}

/**************************************************************************************************
* The error shown when the street partial range is incorrect
**************************************************************************************************/
interface.showStreetPartialError = function()
{
	alert(com.qas.MSG_STREETPARTIAL_ERROR);
	document.getElementById("partial_input").value = "";
	events.handleClickShowPartialResults();
}

/**************************************************************************************************
* The error shown when the premises partial range is incorrect
**************************************************************************************************/
interface.showPremPartialError = function()
{
	alert(com.qas.MSG_PREMPARTIAL_ERROR);
	document.getElementById("partial_input").value = "";
	events.handleClickShowPartialResults();
}

/**************************************************************************************************
* Displays the right hand details box (choose this address/ edit this address)
**************************************************************************************************/
interface.showRightDetails = function(widget)
{
	// Remove the right hand details if they exist
	if (document.getElementById("right_details") != null && 
	document.getElementById("right_details").parentElement != null)
	{
		document.getElementById("right_details").parentElement.
			removeChild(document.getElementById("right_details"));
	}
	
	var h5 = document.createElement("h5");
	h5.innerHTML = "Original Address: ";
	
	var addrss = document.createElement("dt");
	addrss.setAttribute("id", "originaladdress");
	// WE HAVE CHANGED THIS TO USE A TABLE TO BETTER HANDLE WRAPPING SINCE OUR LABELS ARE LONGER THAN THE DEFAULT QAS LABELS
	addrss.innerHTML = "<table>"
		+ "<tr><td>" + com.qas.LINEONE + ":</td><td>" + originaladdress.getLineOne() + "</td></tr>"
		+ "<tr><td>" + com.qas.LINETWO + ":</td><td>" + originaladdress.getLineTwo() + "</td></tr>"
		//+ "<tr><td>" + com.qas.LINETHREE + ":</td><td>" + originaladdress.getLineThree() + "</td></tr>"
		+ "<tr><td>" + com.qas.CITY + ":</td><td>" + originaladdress.getCity() + "</td></tr>"
		+ "<tr><td>" + com.qas.STATE + ":</td><td>" + originaladdress.getState() + "</td></tr>"
		+ "<tr><td>" + com.qas.ZIP + ":</td><td>" + originaladdress.getZip() + "</td></tr>"
		+ "</table>"
	/* - ORIGINAL QAS LAYOUT.
	addrss.innerHTML = "You entered:<br><br>" 
		+ "<label class='qas_rightdetails'>" + com.qas.LINEONE + ": </label>" + originaladdress.getLineOne() + "<br>"
		+ "<label class='qas_rightdetails'>" + com.qas.LINETWO + ": </label>" + originaladdress.getLineTwo() + "<br>"
		+ "<label class='qas_rightdetails'>" + com.qas.LINETHREE + ": </label>" + originaladdress.getLineThree() + "<br>"
		+ "<label class='qas_rightdetails'>" + com.qas.CITY + ": </label>" + originaladdress.getCity() + "<br>"
		+ "<label class='qas_rightdetails'>" + com.qas.STATE + ": </label>" + originaladdress.getState() + "<br>"
		+ "<label class='qas_rightdetails'>" + com.qas.ZIP + ": </label>" + originaladdress.getZip() + "<br><br>";
	*/

	/*var chooselink = document.createElement("dt");
	chooselink.className = "qas_link";
	chooselink.innerHTML = "Choose this address";
	chooselink.onclick = events.handleChooseAddressText;*/
	
	/*
	var choosebutton = document.createElement("input");
	choosebutton.setAttribute("type", "button");
	choosebutton.setAttribute("id", "choose_btnsubmit");
	choosebutton.setAttribute("value", "Choose Address");
	choosebutton.className = "qas_refinebutton";
	choosebutton.onclick = events.handleChooseAddressText;
	*/
	var choosebutton = document.createElement("dt");
	//choosebutton.setAttribute("id", "choose_btnsubmit");
	choosebutton.innerHTML = "Use Original Address";
	choosebutton.className = "qas_link";
	choosebutton.onclick = events.handleChooseAddressText;
	
	
	/*var ortext = document.createElement("dt");
	ortext.setAttribute("id", "ortext");
	ortext.innerHTML = "<p>OR</p>";*/
	
	/*var editlink = document.createElement("dt");
	editlink.className = "qas_link";
	editlink.innerHTML = "Edit this address";
	editlink.onclick = events.handleEditAddressText;*/

	/*var editbutton = document.createElement("input");
	editbutton.setAttribute("type", "button");
	editbutton.setAttribute("id", "edit_btnsubmit");
	editbutton.setAttribute("value", "Edit Address");
	editbutton.className = "qas_refinebutton";
	editbutton.onclick = events.handleEditAddressText;*/
	
	var editlink = document.createElement("a");
	editlink.setAttribute("href", "javascript:void(0);");
	editlink.innerHTML = "[Edit]";
	editlink.className = "qas_link";
	editlink.onclick = events.handleEditAddressText;
	
	
	
	var box = document.createElement("div");
	box.setAttribute("id", "right_details");
	box.className = "proweb_details";
	box.appendChild(h5);
	h5.appendChild(editlink);
	box.appendChild(addrss);
	box.appendChild(choosebutton);
	//box.appendChild(ortext);
	//box.appendChild(editbutton);
	
	document.getElementById(widget).appendChild(box);
}

/**************************************************************************************************
* This creates a div element and adds it to the display
**************************************************************************************************/
interface.addToProwebWidget = function(widget_name)
{
	var widget = document.createElement("div");
	widget.setAttribute("id", widget_name);
	widget.className = (com.qas.RUN_AS_POPUP.toLowerCase() == "true") ? "proweb_popup" : "proweb_nonpopup";
	document.getElementById("proweb_wgt").appendChild(widget);
}

/**************************************************************************************************
* The display when no match can be found (if the user has chosen to not ignore failed matches)
**************************************************************************************************/
interface.showNoResults = function()
{
	document.getElementById("refine_wgt").innerHTML = "";
	
	var msg = document.createElement("dt");
	msg.setAttribute("id", "none_message");
	msg.innerHTML = com.qas.MSG_NONE;
	msg.className = "qas_message";
	document.getElementById("none_wgt").appendChild(msg);
	
	interface.showRightDetails("none_wgt");
	document.getElementById("right_details").className = "proweb_details_left";
	interface.selectDisplay("none_wgt");
}

/**************************************************************************************************
* Commands to run on page creation
**************************************************************************************************/

// ADD THE INITIALIZTION CODE TO THE DOMREADY EVENT
window.addEvent('domready',function(){
	// Add the proweb_wgt and input_wgt to the body
	var pwwgt = document.createElement("div");
	pwwgt.setAttribute("id", "proweb_wgt");
	document.body.appendChild(pwwgt);
	
	var inwgt = document.createElement("div");
	inwgt.setAttribute("id", "input_wgt");
	pwwgt.appendChild(inwgt);
	
	// Add the widgets for the rest of the application
	interface.addToProwebWidget("multiple_wgt");
	interface.addToProwebWidget("partial_wgt");
	interface.addToProwebWidget("refine_wgt");
	interface.addToProwebWidget("interaction_wgt");
	interface.addToProwebWidget("none_wgt");
	//interface.addToProwebWidget("wait_wgt");
	
	// Add the cover widget so that the background can be disabled
	var widget = document.createElement("div");
	widget.setAttribute("id", "cover_wgt");
	widget.className = "proweb_cover";	
	document.body.appendChild(widget);
	
	// CREATE THE WAIT WIDGET HERE. THE ORIGINAL CODE CREATES THIS EVERY TIME QAS IS RUN, SO YOU COULD HAVE MULTIPLE WAIT_WGT DIVS
	var wait = document.createElement("div");
	wait.setAttribute("id", "wait_wgt");
	wait.className = "wait_message";
	wait.innerHTML = promptMsg + " <img src=/qas/qas.gif>";
	document.getElementById("cover_wgt").appendChild(wait);   // will also cause IE to crash if you try to remove it when its appended to the body.. not sure why
	
	// Add all of the event handling dynamically, so as to remove from the interface
	//document.getElementById("input_search").onclick = events.handleClickInputButton;
	
	// Set up the inteface, so that only the prompt screen is showing by default
	interface.selectDisplay("input_wgt");
	
	// Check to see which button should handle the prompt event
	//business.selectInputButton();
	
	// Prevent the submission of the form via the enter key
	//document.onkeypress = events.preventSubmissionFormEnter;
});

