
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// Date: 13 Feb 2009
	//
	// SFAJAX (StoreFinder Ajax) javascript API.
	// Provides StoreFinder subscribers with embedded store locator functionality on their website.
	//
	// Copyright (C) 2008 by Daniel Vidoni, Sydney Australia, All rights reserved.
	// Web: www.storefinder.com.au
	//
	// You may not distribute this code in any manner, modified or otherwise, without the express, written
	// consent from Daniel Vidoni.
	// 
	// You may not make modifications or install this file on your servers.
	//
	// You are permitted to link to this code for the purpose of providing your website with store finder functionality.
	//
	// In all cases copyright and header must remain intact.
	//
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


	var isIE = (window.ActiveXObject) ? true : false;		// browser detection


	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// begin global private variables (do not access or modify from outside scope of this file)
	//
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


	// A javascript, in a normal html document, opens on an http connection: document.location.protocol equals "http" in Konqueror.
	// However in Netscape and Explorer it equals "http:". This can breaks things, therefore we do a case insensitive search for the letter 's'
	// to determine whether we are in secure mode or not.
	var _sslProtocol = (document.location.protocol.search(/s/i) == -1) ? false : true;

	// proxy directory, filename and behavior
	var _proxyDir = "./";
	var _proxy = "sfajaxproxy.php";
	_proxy += (_sslProtocol) ? "?SSL=true" : "?SSL=false";
	
	// storefinder address
	var _storefinderRootURL = (_sslProtocol) ? "https://anchor.net.au/secure/" : "http://www.";
	_storefinderRootURL += "storefinder.com.au";

	var _maps = '';												// map link option ('SFMAPS', 'GOOGLEMAPS' or 'NOMAPS' for no link)
	var _xmlHttp = null;									// XMLHttpRequest object
	var _resultsHTMLTarget;								// results container
	var _dymHTMLTarget;										// 'did you mean' container
	var _resultHTMLTemplate = "";					// template to use for rendering results (optional)

	var _retailerID;											// identifies account holder
	var _retailerText   = "Locations";		// outlet type to display
	var _resultsShuffle =  0;							// true or false (1 or 0) whether or not to shuffle results
	var _radius					= -1;							// search radius in kilometres (-1 means infinite)
	var _numResults			=  3;							// maximum number of results to display
	var _query 					= "";							// query string to pass to engine
	var _marketing			= "";							// optional marketing information
	var _country        = "AU";						// default country


	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// begin handy public functions (can be called safely at any time from beyond the scope of this file)
	//
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


	// Emulate getElementById on document.all only browsers.
	// Requires that IDs are unique to the page and do not coincide with
	// NAME attributes on other elements.
	if( (!document.getElementById) && document.all ) {
		document.getElementById = function(id) {
			return document.all[id];
		};
	}
/*
	if (document.getElementByID) {	// Open standards method
		document.getElementById = function(id) {
			return document.getElementById(id);
		};
	}
	else if(document.all) {					// IE method
		document.getElementById = function(id) {
			return document.all[id];
		};
	}
*/

	// IsDefined:
	// returns true if variable defined
	function IsDefined(variable)
	{
		return ( typeof(variable) == "undefined" ) ? false : true;
	} 


	// IsNumeric: Regular expression that validates a value is numeric
	// Return true or false
	function IsNumeric(x)
	{
		// compare the argument to the RegEx. The 'match' function returns 0 if the value doesn't match
		// Note: this WILL allow a number that ends in a decimal: -452.
		return !!x.match(/^[-+]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)?$/);
	}	


	// PopupURL: opens URL in a non-resizable pop up window (800x700 default size)
	function PopupURL(url, w, h)
	{
		if (!IsDefined(w)) w = 800;
		if (!IsDefined(h)) h = 770;

		urlWindow = window.open ( url, 'Popup','toolbar=0,location=0,directories=0,status=1,menubar=0,scrollbars=1,resizable=0,height='+h+',width='+w);
		urlWindow.focus();
	}


	
	// StripWhitespace: remove whitespace characters from a string
	// returns new formatted string
	function StripWhitespace(s)
	{
		// strip newLine, carriage return and tab characters from xml string
		return s.replace(/[\n\r\t]/g, '');
	}


	// ReplaceAll: replaces all occurences of 'from' with 'to' in string 'str'
	// returns str
	function ReplaceAll( str, from, to )
	{
		var idx = str.indexOf( from );
				
		while ( idx > -1 ) {
			str = str.replace( from, to );
			idx = str.indexOf( from );
		}
		
		return str;
	}


	// CreateNewXMLHttpObject: instantiate and return the best version of the XMLHttpRequest object	
	// returns null on fail
	function CreateNewXMLHttpObject()
	{ 
		var xmlHttp = null;

		try {
			xmlHttp = new XMLHttpRequest();												// Firefox, Opera 8.0+, Safari
		}
		catch (e)	{																							// Internet Explorer
			try {
				xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");			// explorer 6
			}
			catch (e) {
				try {
					xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");	// explorer 5.5
				}
				catch(e) {
					alert("CreateNewXMLHttpObject: " + e.message);
					return null;
				}
			}
		}
	
		return xmlHttp;
	}


	// ParseXML: parse XML to data object
	// returns null on fail
	function ParseXML(xmlResponseText)
	{ 
		var xmlDoc;

//		xmlResponseText = xmlResponseText.replace(/&/g, "&amp;");		// correcting non-XML compliance by HTML encoding '&' to '&amp;' 
		var xmlStr = StripWhitespace(xmlResponseText);							// remove problematic characters from XML string

		try {
			if (isIE) {	// Internet Explorer
				xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
				xmlDoc.async = false;
				xmlDoc.loadXML( xmlStr );
				if (xmlDoc.parseError.errorCode != 0) {
					alert("Parser Error in line " + xmlDoc.parseError.line + " " +
								"position " + xmlDoc.parseError.linePos + "\n" +
								"Error Code: " + xmlDoc.parseError.errorCode + "\n" +
								"Error Reason: " + xmlDoc.parseError.reason + "\n" +
								"Error Line: " + xmlDoc.parseError.srcText);
					document.getElementById('sf_locality').focus();
					return null;
				}
			}
			else {				// Non Explorer Dom parser
				var xmlDoc = new DOMParser().parseFromString( xmlStr, "text/xml" );
				if (xmlDoc.documentElement.nodeName=="parsererror") {
					alert("Parser Error: " + xmlDoc.documentElement.childNodes[0].nodeValue);
					document.getElementById('sf_locality').focus();
					return null;
				}
			}
		}
		catch(e) {
			alert(e.message);
			return null;
		}
		
		return xmlDoc;
	}
	

	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// begin private functions (internal use only)
	//
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


	// _Echo: sends string to destination html target
	// if no destination defined it will go to the 'sf_results' html element
	function _Echo(str, dst) 
	{
		if (IsDefined(dst)) {
			dst.innerHTML += str;
			return;
		}

		_resultsHTMLTarget.innerHTML += str;
	}


	// _GetText: browser safe retrieval of text from a node 
	// returns node value
	function _GetText(node)
	{
		return (isIE) ? node.text : node.textContent;
	}


	// _FindAttribValue: iterates through attribute list searching for string and returns its value
	// returns null on fail
	function _FindAttribValue(attList, str)
	{
		for (a=0; a<attList.length; a++) {
			if ( attList[a].name==str )
				return attList[a].value;
		}
		return null;
	}


	// _ShowLoadingIcon: shows or hides loading icons and 'did you mean' results
	function _ShowLoadingIcon(state)
	{ 
		if (state==true) {
			document.getElementById("sf_loading").style.display  = 'inline';
			document.getElementById("sf_gobutton").style.display = 'none';
			document.getElementById("sf_didyoumean").style.display = 'none';
		}
		else {
			document.getElementById("sf_loading").style.display  = 'none';
			document.getElementById("sf_gobutton").style.display = 'inline';
		}
	}
		
	
	// _InitialiseXmlHttpObject: initialises AJAX xml http object
	// returns false on fail, true on success
	function _InitialiseXmlHttpObject()
	{
		if (_xmlHttp==null) {	// instantiate only once
			_xmlHttp = CreateNewXMLHttpObject();
			if (_xmlHttp==null) {
				alert ("_InitialiseXmlHttpObject: Browser does not support AJAX HTTP Request");
				return false;
			}
		}
		return true;
	}


	// 'Get' functions to simplify access to mandatory fields
	// return text content of result field item
	function _GetDistance(resultFields)			 { return _GetText(resultFields[0]); }
	function _GetLocationName(resultFields)	 { return _GetText(resultFields[1]); }
	function _GetStreetAddress(resultFields) { return _GetText(resultFields[2]); }
	function _GetAddress2(resultFields)			 { return _GetText(resultFields[3]); }
	function _GetSuburb(resultFields)				 { return _GetText(resultFields[4]); }
	function _GetPostcode(resultFields)			 { return _GetText(resultFields[5]); }


	// _DisplayUserDefinedResultItem: renders one discreet result item from non-mandatory fields
	function _DisplayUserDefinedResultItem(resItem, showName)
	{ 
		attr = resItem.attributes;

		if ( attr.length==1 ) {
			_Echo(_GetText(resItem));
			return;
		}

		// don't display this field if the display flag is set to NO or XMLOnly
		if ( _FindAttribValue(attr, 'display').search(/y/i) == -1)
			return;

		// extract field name for use in switch statement
		var name = "";
		if (IsDefined(showName)) {
			if (!!(name = _FindAttribValue(attr, "name")))
				name += ": ";
		}

		// extract type information for use in following switch statement
		type = (attr[1].name=="type") ? attr[1].value : "";

		itemStr = _GetText(resItem);

		// modify display behaviour based on object type...

		switch (type.toUpperCase()) {

			case 'EMAIL':		_Echo(name + "<a href='mailto:" + itemStr + "'>" + itemStr + "</a>");
											break;

			case 'URL':			prefix = ( itemStr.search(/http:\/\//i)==-1 ) ? "http://" : "";
											_Echo(name + "<a href='" + prefix + itemStr + "' target='_blank'>" + itemStr + "</a>");
											break;

			case 'LINK':		urlvars = itemStr.split(";");
											prefix = ( urlvars[1].search(/http:\/\//i)==-1 ) ? "http://" : "";
											_Echo(name + "<a href='" + prefix + urlvars[1] + "' target='_blank'>" + urlvars[0] + "</a>");
											break;

			case 'IMAGE':		prefix = ( itemStr.search(/http:\/\//i)==-1 ) ? "http://" : "";
											_Echo( name + "<img src='" + _storefinderRootURL + "/postcode/core/libs/image_resize.php?i=" + prefix + itemStr + "&w=160&h=160' border='1' hspace='5' vspace='5' align=\"top\" title='" + name + "'>" );
											break;

			case 'IMAGELINK':
											urlvars = itemStr.split(";");
											alert(urlvars[0] + "  " + urlvars[1]);
											prefixImg = ( urlvars[0].search(/http:\/\//i)==-1 ) ? "http://" : "";
											prefixLnk = ( urlvars[1].search(/http:\/\//i)==-1 ) ? "http://" : "";
											_Echo( "<a href='" + prefixLnk + urlvars[1] + "' target='_blank'> <img src='" + _storefinderRootURL + "/postcode/core/libs/image_resize.php?i=" + prefixImg + urlvars[0] + "&w=160&h=160' border='1' hspace='5' vspace='5' align=\"top\" title='" + name + "'></a>" );
											break;

			default:				_Echo(name + _GetText(resItem));
											break;
		}
	}


	// _DisplayResult: renders one entire self-contained result panel
	function _DisplayResult(resultFields) 
	{
		// load results details
		var dist     = _GetDistance(resultFields);
		var bizName  = _GetLocationName(resultFields);
		var addr1    = _GetStreetAddress(resultFields);
		var addr2    = _GetAddress2(resultFields);
		var suburb   = _GetSuburb(resultFields);
		var pcode    = _GetPostcode(resultFields);

		var addrStr1 = (addr1) ? addr1 + ", " : "";																							// address 1 is optional
		var addrStr2 = (addr2) ? addr2 + ", " : "";																							// address 2 is optional

		// render distance
		distStr = (dist<=1) ? "Within 1 km" : "Approx. " + dist + " kms";
		_Echo("<span class='sf_result_header'>" + distStr +	"&nbsp; </span><br>");							// distance

		_Echo("<span style='margin-left:45px;'><strong>" + bizName + "</strong></span><br>");		// business name
		
		// render address
		if (addr1) _Echo("<span style='margin-left:45px;'>" + addrStr1 + "</span><br>");					
		if (addr2) _Echo("<span style='margin-left:45px;'>" + addrStr2 + "</span><br>");
		_Echo("<span style='margin-left:45px;'>" + suburb + "&nbsp; " + pcode + "</span><br>");	// suburb and postcode

		// render map link
		if (addr1) {
			if (_maps=='GOOGLEMAPS') {					// google maps button link
				_Echo("<a style='margin-left:45px;' target='_blank' " +
								"href='http://maps.google.com.au/maps?q=" + encodeURIComponent(addrStr1) +
																														encodeURIComponent(suburb) + ", " +
																														pcode + ", " +
																														_country + "'>" +
								"<img src='" + _storefinderRootURL + "/widgets/googlemap.jpg' title='View Google Map' border='0' hspace='0' vspace='5' " +
									"style='margin-bottom:8px; padding:1px; border:solid #bbbbbb 1px;'>" +
							"</a>");
			}
			else if (_maps=='SFMAPS') {					// storefinder maps button link
				_Echo("<a style='margin-left:45px; color:#5555dd; font-weight:bold; font-size:11px;' href='javascript:;' " +
								"onClick='javascript:PopupURL(\"" + _storefinderRootURL + "/postcode/core/storefinder-map.php?" +
								"RetailerID=" + _retailerID +
								"&name=" 			+ encodeURIComponent(bizName) +
								"&addr=" 			+ encodeURIComponent(addr1) +
								"&addr2=" 		+ encodeURIComponent(addr2) +
								"&suburb=" 		+ encodeURIComponent(suburb) +
								"&postcode=" 	+ pcode +
								"&country=" 	+ _country +
								"\")'>" +
								"<img src='" + _storefinderRootURL + "/widgets/sfmap.gif' title='View Map' border='0' hspace='0' vspace='5' align='absmiddle' " +
									"style='margin-bottom:15px; padding:1px 8px 0px 0px; border:solid #bbbbbb 0px;'>View Map" +
							"</a>");
			}
		}
		
		// continue with additional optional fields...
		_Echo("<br>");
		for (j=6; j<resultFields.length; j++) {
			if (_GetText(resultFields[j])) {			// ignore empty fields
				_Echo("<img src='" + _storefinderRootURL + "/widgets/bullet-arrow.gif' border='0' width='8' height='8' hspace='0' vspace='0' align='baseline' style='margin-left:45px;'>&nbsp; ");
				_DisplayUserDefinedResultItem(resultFields[j], true);
				_Echo("<br>");
			}
		}

		_Echo("<br><br>");
	}


	// _DisplayResultUsingTemplate: renders one entire self-contained result panel using loaded templates
	function _DisplayResultUsingTemplate(resultFields)
	{ 	
		if (!_resultHTMLTemplate) {
			alert("_DisplayResultUsingTemplate: no template loaded");
			return false;
		}
		
		var scratchTemplate = _resultHTMLTemplate;

		scratchTemplate = ReplaceAll( scratchTemplate, "<% SF_DISTANCE %>",			 _GetDistance(resultFields))
		scratchTemplate = ReplaceAll( scratchTemplate, "<% SF_LOCATION_NAME %>", _GetLocationName(resultFields));
		scratchTemplate = ReplaceAll( scratchTemplate, "<% SF_STREET_ADDR %>",	 _GetStreetAddress(resultFields));
		scratchTemplate = ReplaceAll( scratchTemplate, "<% SF_ADDR2 %>",				 _GetAddress2(resultFields));
		scratchTemplate = ReplaceAll( scratchTemplate, "<% SF_SUBURB %>",				 _GetSuburb(resultFields));
		scratchTemplate = ReplaceAll( scratchTemplate, "<% SF_POSTCODE %>",			 _GetPostcode(resultFields));

		for (j=6; j<resultFields.length; j++) {
			scratchTemplate = ReplaceAll( scratchTemplate, "<% SF_USER_FIELD_" + (j-5) + " %>", _GetText(resultFields[j]) );
		}

		_Echo(scratchTemplate + "<br>");
		return true;
	}


	//  _StateChangedResults_CB: callback function processes results of AJAX call
	function _StateChangedResults_CB() 
	{ 
		if (!(_xmlHttp.readyState==4 || _xmlHttp.readyState=="complete"))
			return;

		// clean results html
		_resultsHTMLTarget.innerHTML = "";
		_dymHTMLTarget.innerHTML     = "";

		_ShowLoadingIcon(false);

		// parse XML to data object

//			var xmlDoc = _xmlHttp.responseXML;
		var xmlDoc = ParseXML(_xmlHttp.responseText);
		if (!xmlDoc)
			return;

		// check for store finder error values

		err = xmlDoc.getElementsByTagName("error");
		if (err.length!=0) {
			errStr = _GetText(err[0].childNodes[0]);
			_Echo("<br><center><img src=\"" + _storefinderRootURL + "/widgets/exclamation-triangle.gif\" alt=\"Error\" width=\"52\" height=\"50\" hspace=\"5\" vspace=\"0\" border=\"0\" align=\"absmiddle\">" + errStr + "</center>");
			document.getElementById('sf_locality').select();
			return;
		}

		// check for locality results
		
		localities = xmlDoc.getElementsByTagName("locality");			
		if (localities.length!=0) {
			for (i=0; i<localities.length && i<8; i++) {			// limit to a max of 8 'did you mean' choices
				loc   = _GetText(localities[i].childNodes[0]);
				state = _GetText(localities[i].childNodes[1]);
				pc    = _GetText(localities[i].childNodes[2]);
				_Echo("<a href=\"javascript:;\" onClick=\"javascript:document.getElementById('sf_locality').value='" + pc + "'; SFAJAXShowResults('" + pc + "');\">" + loc + ", " + state + " &nbsp;" + pc + "</a><br>", _dymHTMLTarget);
			}
			document.getElementById("sf_didyoumean").style.display = 'block';
			document.getElementById('sf_locality').focus();
			return;
		}

		// render results (if any)
		
		results = xmlDoc.getElementsByTagName("result");
		if (results.length!=0) {

			// extract and show header information			
			headerItem = xmlDoc.getElementsByTagName("header")[0].childNodes;
			loc      = _GetText(headerItem[0]);
			state    = _GetText(headerItem[1]);
			pc       = _GetText(headerItem[2]);
			_country = _GetText(headerItem[3]);
			if (_maps=="")
				_maps	= _GetText(headerItem[4]);
			if (loc)		 document.getElementById('sf_locality').value = loc;
			else if (pc) document.getElementById('sf_locality').value = pc;
			_Echo("<br><span class='sf_results_heading'><center>Nearest " + _retailerText + "<br>to <b>" + loc + " " + state + " " + pc + "</b></center></span><br>");
			
			// render results
			for (i=0; i<results.length; i++) {
				if (_resultHTMLTemplate) {
					_DisplayResultUsingTemplate(results[i].childNodes);
				}
				else {
					if (i<10) _Echo("<img src=\"" + _storefinderRootURL + "/widgets/numbers/Num" + (i+1) + ".gif\" alt=\"\" border=\"0\" align=\"absmiddle\">");
					else			_Echo("<img src=\"" + _storefinderRootURL + "/widgets/S.gif\" alt=\"\" border=\"0\" align=\"absmiddle\">");
					_DisplayResult(results[i].childNodes);
				}
			}

		}
		else {
			_Echo("<br><span class='sf_results_heading' style='color:#333333;'><center>No results found.</center></span>");
			document.getElementById('sf_locality').focus();
		}

		// add footer
//		_Echo( "<br><p style='text-align:center; border-top:solid 1px #bbbbbb; font-size:9pt; color:#F8A21B; padding-top:5px;'>" +
//					"Provided by <a href='http://www.storefinder.com.au' target='_blank' style='text-decoration:none; font-size:9pt; color:#0871D9;'>" +
//					"<img src='" + _storefinderRootURL + "/widgets/S.gif' width='14' height='14' alt='' border='0' align='absmiddle'> StoreFinder</a></p>" );
	}


	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// begin public SFAJAX functions ( API )
	//
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	
	// SFAJAXInitialise: initialises relevant variables for safe functioning of SFAJAX
	// returns false on fail, true on success
	function SFAJAXInitialise(retailerID, retailerText, maps, resultsShuffle)
	{
		_resultsHTMLTarget = document.getElementById("sf_results");
		_resultsHTMLTarget.innerHTML = "";
		
		_dymHTMLTarget = document.getElementById("sf_didyoumean");
		_dymHTMLTarget.innerHTML = "";

		if (!IsNumeric(retailerID) || retailerID=="" || retailerID==0) {
			alert("SFAJAXInitialise: " + retailerID + " ID Invalid.");
			return false;
		}
		_retailerID = retailerID;
		if (IsDefined(retailerText))   _retailerText   = retailerText;
		if (IsDefined(resultsShuffle)) _resultsShuffle = resultsShuffle;
		if (IsDefined(maps)) 		 			 _maps			 		 = maps;

		if (!_InitialiseXmlHttpObject())
			return false;

		document.getElementById('sf_locality').focus();
		return true;
	}


	// SFAJAXSetProxyLocation: sets a new directory/location on the server for the proxy file.
	// returns previous proxy file directory
	function SFAJAXSetProxyLocation(dir)
	{
		var prevDir = _proxyDir;
		
		if (!IsDefined(dir) || !dir)
			alert("SFAJAXSetProxyLocation: No directory name specified.");
		else
			_proxyDir = dir;
		
		return prevDir;
	}
	
	
	// SFAJAXLoadFile: load a file from a local domain url.
	// NB: Only works for files within current domain.
	// returns null on fail, file content on success
	function SFAJAXLoadFile(fileName)
	{
		if (!IsDefined(fileName) || !fileName) {
			alert("SFAJAXLoadFile: No file name specified.");
			return false;
		}
		
		if (!_InitialiseXmlHttpObject())
			return null;

		_xmlHttp.open("GET", fileName, false);	// synchronous ajax get
		_xmlHttp.send(null);
		return _xmlHttp.responseText;
	}


	// SFAJAXLoadResultTemplate: load a template file from a local domain url.
	// NB: Only works for files within current domain.
	// returns false on fail, true on success
	function SFAJAXLoadResultTemplate(fileName)
	{
		if (!IsDefined(fileName) || !fileName) {
			alert("SFAJAXLoadResultTemplate: No file name specified.");
			return false;
		}
		
		if (!_InitialiseXmlHttpObject())
			return false;

		_xmlHttp.open("GET", fileName, false);	// synchronous ajax get
		_xmlHttp.send(null);

		_resultHTMLTemplate = _xmlHttp.responseText;
		return true;
	}


	// SFAJAXLoadFileIntoHTMLElement: load an html file containing the form widget into the (optional) destination html id tag.
	// NB: Only works for files within current domain.
	// returns false on fail, true on success
	function SFAJAXLoadFileIntoHTMLElement(formFileName, dstID)
	{
		if (!IsDefined(formFileName) || !formFileName) {
			alert("SFAJAXLoadFileIntoHTMLElement: No file name specified.");
			return false;
		}

		if (!IsDefined(dstID)) {
			alert("SFAJAXLoadFileIntoHTMLElement: No destination element specified.");
			return false;
		}

		fileContent = SFAJAXLoadFile(formFileName);
		if (!fileContent)
			return false;

		_Echo(fileContent, document.getElementById(dstID));
		return true;
	}


	// SFAJAXShowResults: setup AJAX call using passed arguments
	// returns false on fail, true on success
	function SFAJAXShowResults(location, query, radius, numResults, market)
	{ 
		if (_xmlHttp==null)	{ // ensure xml system instantiated
			alert("SFAJAXShowResults: StoreFinder AJAX module not initialised!");
			document.getElementById('sf_locality').select();
			return false;
		}

		if (!IsDefined(location) || location=="") {
			alert("Please enter a 3 or 4 digit postcode, or locality name.");
			document.getElementById('sf_locality').select();
			return false;
		}
		if (location.search(',')!=-1 || location.search('/')!=-1) {
			alert("Please enter either a town, suburb or postcode.");
			document.getElementById('sf_locality').select();
			return false;
		}

		if (!IsNumeric(location) && location.length<3) {			// interesting note: shortest town name in Australia is 'Me'
			alert("Please enter a valid town or suburb name.");
			document.getElementById('sf_locality').select();
			return false;
		}
		if (IsNumeric(location) && (location<100 || location>9999)) {
			alert("Please enter a valid 3 or 4 digit postcode.");
			document.getElementById('sf_locality').select();
			return false;
		}

		if (IsDefined(query)) 		 _query  = query;
		if (IsDefined(radius)) 		 _radius = parseInt(radius,10);
		if (IsDefined(numResults)) _numResults = numResults;
		if (IsDefined(market)) 		 _marketing	 = market;

		_ShowLoadingIcon(true);

		// For security reasons the XMLHttpRequest Object only works within a domain !
		// This means that calls to locations outside the domain leads to security errors such as:
		//   [ Exception... "Access to restricted URI denied" code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI) ]
		// We use a serverside page proxy that works around the cross domain issue by taking the request on the users server
		// and sending it from there to the StoreFinder site, then return the value via the proxy back to the user.
		var timestamp = new Date();
		var urlStr = _proxyDir + _proxy + "&RetailerID="			+ _retailerID +
																			"&Postcode="				+ encodeURIComponent(location) +
																			"&Marketing="				+ encodeURIComponent(_marketing) +
																			"&Radius="					+ _radius +
																			"&Results="					+ _numResults +
																			"&ResultsShuffle=" 	+ _resultsShuffle +
																			"&Query="						+ encodeURIComponent(_query) +
																			"&TimeStamp="				+ timestamp.getTime();				// avoid caching

		_xmlHttp.open("GET", urlStr, true);
		_xmlHttp.onreadystatechange = _StateChangedResults_CB;
		_xmlHttp.send(null);
		
		return true;
	}


	// SFAJAXInstallDefaultWidget: dynamically generates HTML form code inserted at page load time and
	// initialises SFAJAX system.
	function SFAJAXInstallDefaultWidget(retailerID, retailerText, maps, resultsShuffle)
	{
		document.write("<form onSubmit=\"SFAJAXShowResults(document.getElementById('sf_locality').value); return false;\">" +

											"<table border='0' align='center' cellpadding='0' cellspacing='0'>" +

												"<tr>" +
													"<td width='115' rowspan='3'>&nbsp;</td>" +
													"<td colspan='3' valign='middle' align='center' style='font-size:12px; padding:6px; color:#444444; border-top:solid #cccccc 1px; " +
														"background-color:#FFFFFF; background-image:url(" + _storefinderRootURL + "/widgets/shadow.gif);	background-position:0px -3px;'>" +
														"<strong>Enter your town or suburb or postcode:</strong></td>" +
													"<td width='115' rowspan='3'>&nbsp;</td>" +
												"</tr>" +

												"<tr>" +
													"<td width='30' style='padding:0px 5px 4px 5px; border-bottom:solid #bbbbbb 1px; background-color:#FFFFFF;'>" +
														"<img id='sf_gobutton' style='display:inline;' src='" + _storefinderRootURL + "/widgets/S.gif' alt='' border='0'>" +
														"<img id='sf_loading' style='display:none;' src='" + _storefinderRootURL + "/widgets/loading_blue.gif' border='0' width='24' height='24' vspace='5'>" +
//														"<img src='" + _storefinderRootURL + "/widgets/indicator_arrows.gif' name='sf_loading' vspace='9' border='0' id='sf_loading' style='display:none;'>" +
//														"<img src='" + _storefinderRootURL + "/widgets/loading_grey_sweep.gif' name='sf_loading' width='25' height='25' vspace='4' border='0' id='sf_loading' style='display:none;'>" +
													"</td>" +
													"<td width='115' valign='middle' style='padding:0px 10px 0px 10px; background-color:#eeeeee; border-top:solid #bbbbbb 1px; border-left:solid #bbbbbb 1px; border-right:solid #aaaaaa 2px;'>" +
														"<input type='text' id='sf_locality' size='14' maxlength='32' style='color:#0871D9;'>" +
													"</td>" +
													"<td width='115' align='center' valign='middle' style='padding:0px 5px 4px 5px; border-bottom:solid #bbbbbb 1px; background-color:#FFFFFF;'>" +
														"<input type='image' value='Search' title='Search & locate nearest' " +
															"src='" + _storefinderRootURL + "/widgets/search_big.jpg' " +
															"onMouseOut='this.src =\""  + _storefinderRootURL + "/widgets/search_big.jpg\"' " +
															"onMouseOver='this.src =\"" + _storefinderRootURL + "/widgets/search_big_ov.jpg\"'>" +
													"</td>" +
												"</tr>" +

												"<tr>" +
													"<td colspan='3'>" +
														"<div id='sf_didyoumean' class='sf_didyoumean' style='display:none;'></div></td>" +		// populated with place name matches
												"</tr>" +

												"<tr>" +
													"<td colspan='5'>" +
														"<span id='sf_results' class='sf_results'></span></td>" +															// populated with results output and error messages
												"</tr>" +

											"</table>" +

										"</form>");

		// add footer
		document.write("<br><br><p style='text-align:center; border-top:solid 1px #bbbbbb; font-size:9pt; color:#F8A21B; padding-top:5px;'>" +
					"Provided by <a href='http://www.storefinder.com.au' target='_blank' style='text-decoration:none; font-size:9pt; color:#0871D9;'>" +
					"<img src='" + _storefinderRootURL + "/widgets/S.gif' width='14' height='14' alt='' border='0' align='absmiddle'> StoreFinder</a></p>" );

		SFAJAXInitialise(retailerID, retailerText, maps, resultsShuffle);
	}


	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//
	// END OF SFAJAX MODULE.
	//
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
