/********************************************************************************
// This is a collection of JavaScript code to allow easy integration of 
// postcode lookup functionality into any website
//
// Provided by www.CraftyClicks.co.uk
//
// Version - 3.5  (05/10/2009)
//
// Feel free to copy/use/modify this code any way you see fit. Please keep this
// comment header in place when you do.
//
// To integrate UK postcode lookup on your website, please visit www.craftyclicks.co.uk for
// details of how to sign up for an account.
**********************************************************************************/
var _cp_instances = new Array();
var _cp_instance_idx = 0;
function CraftyPostcodeCreate() {
	_cp_instance_idx++;
	_cp_instances[_cp_instance_idx] = new CraftyPostcodeClass();
	_cp_instances[_cp_instance_idx].obj_idx = _cp_instance_idx;
	return _cp_instances[_cp_instance_idx];
}
var _cp_arr_sort_dl = ',';
function _cp_arr_compare(a,b) {
	// see if there is a number at the start and compare that first
	var numA; var numB;
	// check for a flat
	if ('FLAT' == a['str'].substr(0,4).toUpperCase() && 'FLAT' == b['str'].substr(0,4).toUpperCase()) {
		numA = parseInt(a['str'].substr(5,a['str'].indexOf(_cp_arr_sort_dl,5)));
		numB = parseInt(b['str'].substr(5,b['str'].indexOf(_cp_arr_sort_dl,5)));
	} else {
		numA = parseInt(a['str']);
		numB = parseInt(b['str']);
	}
	if (numA > numB) { return (1);}
	if (numA < numB) { return (-1);}
	// if we get here that means either no number at start, or both numbers the same
	if (a['str'] > b['str']) { return (1); }
	return (-1);
}
function _cp_res_key_press(e) {
	if (!e) e = window.event;
	if(e.keyCode) {cc = e.keyCode;}
	else if(e.which) {cc = e.which;}
	if(cc == 13){
		this.onclick();
	}
}

function CraftyPostcodeClass () {
	this.config = { 
		lookup_url		: 'pcls1.craftyclicks.co.uk/lookup_js.php', // url to use for lookup
		access_token	: '', // specify access token here to use the direct JS method,  lookup_url must be set to 'http://pcls1.craftyclicks.co.uk/lookup_js.php'
		traditional_county	: 0, // 0 - postal county, 1 - traditional county name
		busy_img_url	: 'crafty_postcode_busy.gif',	// full url of the gif to show when waiting for result
		hide_result		: 0,		// 1 - results box disappears once a result is clicked, 0 - it stays up
		org_uppercase	: 1,		// 0 - leading uppercase, 1- all in uppercase
		town_uppercase	: 1,		// 0 - leading uppercase, 1- all in uppercase
		county_uppercase: 0,		// 0 - leading uppercase, 1- all in uppercase
		addr_uppercase	: 0,		// 0 - leading uppercase, 1- all in uppercase
		delimiter		: ', ',
		msg1			: 'please wait while we find the address',
		err_msg1		: 'this postcode could not be found, please try again',
		err_msg2		: 'this postcode is not valid, please try again',
		err_msg3		: 'unable to connect to address lookup server',
		err_msg4		: 'an unexpected error occured',
		res_autoselect	: 1, // the first result will be auto-selected by default
		res_select_on_change : 1, // 1 - if the user scrolls through the results they will be selected, 0 - user must explicitly click to select 
		debug_mode		: 0,
		lookup_timeout	: 10000, // time in ms
		form			: '',	// if left blank in/out elements will be shearched by id, if provided elemts will be searched by name
		elements		: 'crafty_out_company,crafty_out_street1,crafty_out_street2,crafty_out_street3,crafty_out_town,crafty_out_county,crafty_in_out_postcode,', // element ids or form fields
		max_width		: '400px',  // width of the results box in px
		max_lines		: 0,		// height of the results box in text lines
		first_res_line	: '', // adds a dummy 1st line  eg '----- please select your address ----'
		result_elem_id	: '',
		verified_postcode	: 'verified_postcode', //Jianway JM 2009-11-25: added to store verified postcode
		on_result_ready : null,
		on_result_selected : null,
		on_error : null
	};

	this.xmlhttp = null;
	this.res_arr = null;
	this.disp_arr = null;
	this.res_arr_idx = 0;
	this.cc = 0;
	this.res_locality = null;
	this.clean_pc = '';
	this.lookup_timeout = null;
	this.obj_name = '';

	this.set = function(field, val){
		this.config[field] = val;
	}

	this.res_clicked = function(idx) {
		this.cc++;
		if (this.res_selected(idx)) {
			if(0 != this.config.hide_result && ( (2 >=this.config.max_lines && 1 < this.cc) || (2 < this.config.max_lines) ) ) {
				this.update_res(null);
				this.cc = 0;
			}
		}
	}
	
	this.res_selected = function(index) {
		if ('' != this.config.first_res_line) {
			if (0 == index) {
				return 0; // don't select the dummy first line if present
			} else {
				index--;
			}
		}

		var elem = new Array();
		var dc = this.config.delimiter;
		
		for (i=0; i<6; i++) {
			elem[i] = this.get_elem(i);
		}	
		// translate index
		index = this.disp_arr[index]['index'];
		var selected_line = this.res_arr[index]; 

		if (elem[0]) { // company
			elem[0].value = selected_line['org'];
		}

		var str1 = selected_line['street1'];
		var str2 = selected_line['street2'];
		var combined_street =  str2 + (str2==''?'':dc) + str1;
		var locality_dep = this.res_locality['locality_dep'] ;
		var locality = this.res_locality['locality'] ;
		if ('' != combined_street && parseInt(combined_street) == combined_street) {
			if ('' != locality_dep) {
				locality_dep = parseInt(combined_street) + ' ' + locality_dep;
			} else {
				locality = parseInt(combined_street) + ' ' + locality;
			}
			combined_street = ''; str1 = '';
		}
		var combined_loc =  locality_dep + (locality_dep==''?'':dc) + locality;
		var combined_str_loc = combined_street + (combined_street==''?'':dc) + combined_loc;
		
		if (elem[1] && elem[2] && elem[3]) {
			if ('' != selected_line['pobox'] || '' != selected_line['housename']) {
				if ('' != selected_line['pobox']) { elem[1].value = selected_line['pobox']; } else { elem[1].value = selected_line['housename']; }
				if ('' == combined_loc) {
					if ('' == str2) {
						elem[2].value = str1;
						elem[3].value = '';
					} else {
						elem[2].value = str2;
						elem[3].value = str1;
					}
				} else if ('' == combined_street) {
					if ('' == locality_dep) {
						elem[2].value = locality;
						elem[3].value = '';
					} else {
						elem[2].value = locality_dep;
						elem[3].value = locality;
					}
				} else {
					elem[2].value = combined_street;
					elem[3].value = combined_loc;
				}
			} else if ('' == combined_street) { 
				if ('' == locality_dep) {
					elem[1].value = locality;
					elem[2].value = '';
					elem[3].value = '';
				} else {
					elem[1].value = locality_dep;
					elem[2].value = locality;
					elem[3].value = '';
				}
			} else if ('' == combined_loc) { 
				if ('' == str2) {
					elem[1].value = str1;
					elem[2].value = '';
					elem[3].value = '';
				} else {
					elem[1].value = str2;
					elem[2].value = str1;
					elem[3].value = '';
				}
			} else { 
				if ('' == str2) {
					elem[1].value = str1;
					if ('' == locality_dep) {
						elem[2].value = locality;
						elem[3].value = '';
					} else {
						elem[2].value = locality_dep;
						elem[3].value = locality;
					}
				} else {
					if ('' == locality_dep) {
						elem[1].value = str2;
						elem[2].value = str1;
						elem[3].value = locality;
					} else {
						if (combined_street.length < combined_loc.length) {
							elem[1].value = combined_street;
							elem[2].value = locality_dep;
							elem[3].value = locality;
						} else {
							elem[1].value = str2;
							elem[2].value = str1;
							elem[3].value = combined_loc;
						}
					}
				}
			} 
		} else if (elem[1] && elem[2])	{
			if ('' != selected_line['pobox']) {
				elem[1].value = selected_line['pobox'];
				elem[2].value = combined_str_loc; // might be blank
			} else if ('' == selected_line['housename'] && '' != combined_street) {
				if ('' == combined_loc) {
					if ('' != str2) {
						elem[1].value = str2;
						elem[2].value = str1;
					} else {
						elem[1].value = combined_street;
						elem[2].value = '';
					}
				} else {
					elem[1].value = combined_street;
					elem[2].value = combined_loc;
				}
			} else if ('' == combined_street && '' != selected_line['housename']) {
				elem[1].value = selected_line['housename'];
				elem[2].value = combined_loc;
			} else if ('' == combined_loc ) { // got house, street but no loc
				elem[1].value = selected_line['housename'];
				elem[2].value = combined_street;
			} else { // got it all baby! spread it evenly
				if ((selected_line['housename'].length + combined_street.length) < (combined_street.length + combined_loc.length)) {
					elem[1].value = selected_line['housename'] + dc + combined_street;
					elem[2].value = combined_loc;
				} else {
					elem[1].value = selected_line['housename'];
					elem[2].value = combined_street + dc + combined_loc;
				}
			} 
		} else { // only got one line!
			var single_elem;
			if (elem[1]) { single_elem = elem[1]; } else if (elem[2]) { single_elem = elem[2]; } else { single_elem = elem[3]; }
			if ('' != selected_line['pobox']) {
				single_elem.value = selected_line['pobox'] + dc + combined_loc;
			} else {
				single_elem.value = selected_line['housename'] + (selected_line['housename']==''?'':dc) + combined_street + (combined_street==''?'':dc) + combined_loc;
			}
		}
		
		if (elem[4]) {
			elem[4].value = this.res_locality['town'];
		}
		
		if (elem[5]) {
			elem[5].value = this.res_locality['county'];
		}

		if (this.config.on_result_selected) {
			this.config.on_result_selected(index);
		}

		return 1;
	}

	this.show_busy = function() {
		var bi = document.createElement('img');
		var na = document.createAttribute('src');
		na.value = this.config.busy_img_url;
		bi.setAttributeNode(na);
		na = document.createAttribute('title');
		na.value = this.config.msg1;
		bi.setAttributeNode(na);
		this.update_res(bi);
	}

	this.disp_err = function(error_code, dbg_msg) {
		var err_node = null;	
		if ('' != error_code) 	{	
			var err_decoded_str = '';
			switch (error_code) {
				case '0001':
					err_decoded_str = this.config.err_msg1;
					break;
				case '0002':
					err_decoded_str = this.config.err_msg2;
					break;
				case '9001':
					err_decoded_str = this.config.err_msg3;
					break;
				default:
					err_decoded_str = '('+error_code+') '+this.config.err_msg4;
					break;
			}
			if (this.config.debug_mode) {
				var err_info = '';
				switch (error_code) {
					case '8000': err_info = ' :: No Access Token '; break; 
					case '8001': err_info = ' :: Invalid Token Format '; break; 
					case '8002': err_info = ' :: Invalid Token '; break; 
					case '8003': err_info = ' :: Out of Credits '; break; 
				}
				err_decoded_str += err_info+' :: DBG :: '+dbg_msg;
			}
			err_node = document.createTextNode(err_decoded_str);
		}	
		this.update_res (err_node);
		if (this.config.on_error) {
			this.config.on_error(err_decoded_str);
		}
	}

	this.disp_err_msg = function(error_msg) {
		var err_node = null;
		if ('' != error_msg) {	
			err_node = document.createTextNode(error_msg);
		}	
		this.update_res (err_node);
		if (this.config.on_error) {
			this.config.on_error(error_msg);
		}
	}

	this.display_res_line = function(dispstr, index) {
		// see if an options box exists already
		postcodeResult = document.getElementById("crafty_postcode_lookup_result_option"+this.obj_idx);

		if (null != postcodeResult) {	// just add a new line to existing select box
			var newOption = document.createElement('option');
			newOption.appendChild(document.createTextNode(dispstr));
			postcodeResult.appendChild(newOption);
		} else {	// create a new select drop down list
			var newOption = document.createElement('option');
			newOption.appendChild(document.createTextNode(dispstr));
			var newSelection = document.createElement('select');
			newSelection.id = 'crafty_postcode_lookup_result_option'+this.obj_idx;
			newSelection.onclick=Function("_cp_instances["+this.obj_idx+"].res_clicked(this.selectedIndex);");
			newSelection.onkeypress=_cp_res_key_press;

			if (0 != this.config.res_select_on_change) {newSelection.onchange=Function("_cp_instances["+this.obj_idx+"].res_selected(this.selectedIndex);");}
			newSelection.style.width=this.config.max_width;
			var num_res_lines = this.res_arr_idx;
			if ('' != this.config.first_res_line) {
				num_res_lines++;
			}
			if (num_res_lines >= this.config.max_lines) {
				newSelection.size=this.config.max_lines;
			} else 	{
				newSelection.size=num_res_lines;
			}
			newSelection.appendChild(newOption);
			this.update_res(newSelection);
		}
	}

	this.update_res = function(new_element) {
		if (this.lookup_timeout) {
			clearTimeout (this.lookup_timeout);
		}
		try	{
			if (document.getElementById) {
				var the_parent = document.getElementById(this.config.result_elem_id);
				// clear out any existing contents
				if (the_parent.hasChildNodes())	{
					while (the_parent.firstChild) {
						the_parent.removeChild(the_parent.firstChild);
					}
				}

				// insert new contents
				if (null == new_element) {
					new_element = document.createTextNode("\u00A0"); // &nbsp;
				}
				// Jianway JM 2009-11-20: new code to display message and to store verified postcode
				else if (new_element.tagName == "SELECT") {
					msg_element = document.createTextNode("please select address"); // &nbsp;
					the_parent.appendChild(msg_element);

					if(document.getElementById(this.config.verified_postcode)) {
						document.getElementById(this.config.verified_postcode).value = this.get_elem(6).value;
					}
				}
			
				the_parent.appendChild(new_element);
			}
		}
		catch(er) {};
	}

	this.str_trim = function(s) {
		var l=0; 
		var r=s.length -1;
		while(l < s.length && s[l] == ' ') { l++; }
		while(r > l && s[r] == ' ') { r-=1;	}
		return s.substring(l, r+1);
	}

	this.cp_uc = function(text) {
		if ("PC" == text || "UK" == text || "EU" == text) {return (text);}
		var alpha="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		var out_text = '';
		var do_uc = 1;
		var all_uc = 0;
		for (var i=0; i<text.length; i++){
			if (-1 != alpha.indexOf(text.charAt(i))) {
				if (do_uc || all_uc) {
					out_text = out_text + text.charAt(i);
					do_uc = 0;
				} else {
					out_text = out_text + text.charAt(i).toLowerCase();
				}
			} else {
				out_text = out_text + text.charAt(i);
				if (i+2 >= text.length && "'" == text.charAt(i)) { // only one more char left, don't capitalise
					do_uc = 0; 
				} else if ("(" == text.charAt(i)) {
					close_idx = text.indexOf(")",i+1);
					if (i+3 < close_idx) { // more than 2 chars
						all_uc = 0; do_uc = 1;
					} else { // no closing bracket or 2 or les chars in brackets, leave uppercase
						all_uc = 1; 
					}				
				} else if (")" == text.charAt(i)) {
					all_uc = 0; do_uc = 1;
				} else if ("-" == text.charAt(i)) {
					close_idx = text.indexOf("-",i+1);
					if ((-1 != close_idx && i+3 >= close_idx) || i+3 >= text.length) { // less than 2 chars
						all_uc = 0; do_uc = 0;
					} else { // 2 or more chars 
						all_uc = 0; do_uc = 1;
					}		
				} else if (i+2 < text.length && "0" <= text.charAt(i) && "9" >= text.charAt(i)) {
					do_uc = 0;
				} else {
					do_uc = 1;
				}
			}
		}
		return (out_text);
	}

	this.leading_caps = function(txt, dont_do_it) {
		if (0 != dont_do_it || 2 > txt.length) { return (txt) }
		var out_text = '';
		var words = txt.split(" ");
		for (var i=0; i<words.length; i++) {	// each word in turn
			var word = this.str_trim(words[i]);
			if ('' != word)	{
				if ('' != out_text)	{
					out_text = out_text + ' ';
				}
				out_text = out_text + this.cp_uc(word);
			}
		}
		return (out_text);
	}

	this.process_xml = function(tn, cn, ln, rn, pn, on, pc) {
		this.res_arr = new Array();
		this.res_locality = new Array(); 
		this.res_locality['town'] = this.leading_caps(tn, this.config.town_uppercase);
		this.res_locality['locality'] = '';
		this.res_locality['locality_dep'] = '';
		if (2 < ln.length) {
			loc_arr = ln.split("|");
			this.res_locality['locality'] = this.leading_caps(loc_arr[0], this.config.addr_uppercase);
			this.res_locality['locality_dep'] = this.leading_caps(loc_arr[1], this.config.addr_uppercase);
		}
		this.res_locality['county'] = '';
		if (2 < cn.length) {
			county_arr = cn.split('|');
			this.res_locality['county'] = this.leading_caps(county_arr[(this.config.traditional_county != 0 ? 1 : 0)], this.config.county_uppercase);
		}
		this.res_arr_idx = 0;
		if ('' != rn) {
			this.process_ranges(rn);
		}
		if ('' != pn) {
			this.process_points(pn);
		}
		if ('' != on) {
			this.process_orgs(on);
		}
		if (this.res_arr_idx) {
			// sort  & display results
			this.disp_res_arr();
			if ('' != pc) {
				var pe = this.get_elem(6);
				pe.value = pc;
			}

			if (0 != this.config.res_autoselect) {this.res_selected(0);}
			document.getElementById("crafty_postcode_lookup_result_option"+this.obj_idx).focus();
			if (this.config.on_result_ready) {
				this.config.on_result_ready();
			}
		} else {
			this.disp_err( '1205', 'no result to display' );
		}
	}

	this.new_res_line = function() {
		var al = new Array();
		al['org'] = ''; al['housename'] = ''; al['pobox'] = '';
		al['street1'] = ''; al['street2'] = '';
		return (al);
	}

	this.process_ranges = function(txt) {
		var chunk = txt.split(";");
		var count = 0;
		
		while (count < chunk.length) {
			var numrange = chunk[count+1].split("|");
			var streets = chunk[count].split("|");

			count = count + 2;
			for (var i=0; i<numrange.length; i=i+2)	{
				if ('' != numrange[i+1]) {
					var start = numrange[i] * 1;
					var end = numrange[i+1] * 1;
					for (var j=start; j<=end; j=j+2) {
						var al = this.new_res_line();
						al['street1'] = this.leading_caps(streets[0], this.config.addr_uppercase);
						al['street2'] = this.leading_caps(streets[1], this.config.addr_uppercase);
						if ('' != al['street2']) {
							al['street2'] = j.toString() + ' ' + al['street2'];
						} else if ('' != al['street1']) {
							al['street1'] = j.toString() + ' ' + al['street1'];
						} else {
							al['street1'] = j.toString();
						}
						this.res_arr[this.res_arr_idx] = al;
						this.res_arr_idx++;
					}				
				} else {
					var al = this.new_res_line();
					al['street1'] = this.leading_caps(streets[0], this.config.addr_uppercase);
					al['street2'] = this.leading_caps(streets[1], this.config.addr_uppercase);
					if ('' != al['street2']) {
						al['street2'] = numrange[i].toString() + ' ' + al['street2'];
					} else if ('' != al['street1']) {
						al['street1'] = numrange[i].toString() + ' ' + al['street1'];
					} else {
						al['street1'] = numrange[i].toString();
					}
					this.res_arr[this.res_arr_idx] = al;
					this.res_arr_idx++;
				}
			}
		}
	}

	this.process_points = function(txt) {
		var chunk = txt.split(";");
		for (var count=0; count< chunk.length; count++) {
			var al = this.new_res_line();
			var parts = chunk[count].split('|');
			if (4 == parts.length) {
				al['street1'] = this.leading_caps(parts[0], this.config.addr_uppercase);
				al['street2'] = this.leading_caps(parts[1], this.config.addr_uppercase);
				al['housename'] =  this.leading_caps(parts[2] + ((parts[2]!='')&&(parts[3]!='')?this.config.delimiter:'') + parts[3], this.config.addr_uppercase);
				this.res_arr[this.res_arr_idx] = al;
				this.res_arr_idx++;
			}
		}
	}

	this.process_orgs = function(txt) {
		var chunk = txt.split(";");
		for (var count=0; count< chunk.length; count++) {
			var al = this.new_res_line();
			var parts = chunk[count].split('|');
			if (7 == parts.length) {
				al['street1'] = this.leading_caps(parts[0], this.config.addr_uppercase);
				al['street2'] = this.leading_caps(parts[1], this.config.addr_uppercase);
				al['housename'] = this.leading_caps(parts[2] + ((parts[2]!='')&&(parts[3]!='')?this.config.delimiter:'') + parts[3], this.config.addr_uppercase);
				al['org'] = this.leading_caps((parts[4] + ((parts[4]!='')&&(parts[5]!='')?this.config.delimiter:'') + parts[5]), this.config.org_uppercase);
				al['pobox'] = this.leading_caps(parts[6], this.config.addr_uppercase);
				this.res_arr[this.res_arr_idx] = al;
				this.res_arr_idx++;
			}
		}
	}

	this.disp_res_arr = function() {
		var dc = this.config.delimiter;
		this.disp_arr = new Array();
		// create an unsorted display array
		for (var i=0;i<this.res_arr_idx;i++) {
			var arrayline = this.res_arr[i];
			var dispstr = arrayline['org'] + (arrayline['org'] !='' ? dc : '') + 
						  arrayline['housename'] + (arrayline['housename'] != '' ? dc : '') + 
						  arrayline['pobox'] + (arrayline['pobox'] != '' ? dc : '') + 
						  arrayline['street2'] + (arrayline['street2'] != '' ? dc : '') +
						  arrayline['street1'] + (arrayline['street1'] != '' ? dc : '') +
						  this.res_locality['locality_dep'] + (this.res_locality['locality_dep'] != '' ? dc : '') +
						  this.res_locality['locality'] + (this.res_locality['locality'] != '' ? dc : '') +
						  this.res_locality['town'];

			var displine = new Array();
			displine['index'] = i;
			displine['str'] = dispstr;
			this.disp_arr[i] = displine;
		}
		// sort it
		_cp_arr_compare_dl = this.config.delimiter;
		this.disp_arr = this.disp_arr.sort(_cp_arr_compare);
		// display it
		if ('' != this.config.first_res_line) {
			this.display_res_line(this.config.first_res_line, -1);
		}
		for (var i=0;i<this.res_arr_idx;i++) {
			this.display_res_line(this.disp_arr[i]['str'], i);
		}
	}

	this.get_elem = function(idx) {
		var en = this.config.elements.split(",");
		var el = null;
		if ('' != this.config.form) {
			el = document.forms[this.config.form].elements[en[idx]];
		} else if (document.getElementById) {
			el = document.getElementById(en[idx]);
		}
		return (el);
	}


	this.handle_http_result = function() {
		if(null == this.xmlhttp || this.xmlhttp.readyState != 4) {
			return;
		}
		if(this.xmlhttp.status != 200) {
			this.disp_err('1200', 'xmlhttp status='+this.xmlhttp.status);
			return;
		}
	//alert(this.xmlhttp.getAllResponseHeaders());
	//alert(this.xmlhttp.responseText);
		try {
			this.update_res(null);
			var doc = this.xmlhttp.responseXML.documentElement;
			var ef = doc.getElementsByTagName("ef");
			if (0 != ef.length) {
				var errCode = ef[0].childNodes[0].nodeValue;
				if ('7001' == errCode) {
					var em = doc.getElementsByTagName("em");
					if (0 != em.length) {
						this.disp_err_msg('demo limit reached, please use one of: '+em[0].childNodes[0].nodeValue);
					} else {
						this.disp_err_msg("sorry, demo usage has a daily limit");
					}
				} else {
					this.disp_err(errCode, '');
				}
			} else {
				var tnt = doc.getElementsByTagName("town");
				var cnt = doc.getElementsByTagName("county");
				var lnt = doc.getElementsByTagName("locality");
				var rnt = doc.getElementsByTagName("ranges");
				var pnt = doc.getElementsByTagName("points");
				var ont = doc.getElementsByTagName("orgs");
				var pct = doc.getElementsByTagName("postcode");
				if ( tnt && cnt && lnt && rnt && pnt && ont && pct) {
					var tn = tnt[0].childNodes[0].nodeValue;
					var cn = cnt[0].childNodes[0].nodeValue;
					var ln = lnt[0].childNodes[0].nodeValue;
					var rn = rnt[0].childNodes[0] ? rnt[0].childNodes[0].nodeValue : '';
					var pn = pnt[0].childNodes[0] ? pnt[0].childNodes[0].nodeValue : '';
					var on = ont[0].childNodes[0] ? ont[0].childNodes[0].nodeValue : '';
					var pc = pct[0].childNodes[0].nodeValue;
					this.process_xml(tn, cn, ln, rn, pn, on, pc);
				} else {
					this.disp_err( '1204', 'An xml tag is missing.' );
				}
			}
		}
		catch(er) {
			this.disp_err( '1201', er );
		}
	}

	this.doLookup = function() {
		this.xmlhttp=null;

		var pe = this.get_elem(6);
		var pc = null;

		if (pe) { 
			this.show_busy(); // show busy img - this will clear any errors/previous results
			this.lookup_timeout = setTimeout ( "_cp_instances["+this.obj_idx+"].lookup_timeout_err()", this.config.lookup_timeout );
			pc = this.validate_pc(pe.value);
		}
		
		if (null != pc) {
			if ('' != this.config.access_token) {
				var inc = pc.substring(pc.length-3,pc.length);
				var outc = pc.substring(0, pc.length-3);
				this.clean_pc = outc+' '+inc;
				this.direct_xml_fetch(pc, this.config.access_token);
			} else {
				var url = this.config.lookup_url+'?postcode='+pc;
				if (window.XMLHttpRequest) {// code for IE7, Firefox, Mozilla, etc.
					this.xmlhttp=new XMLHttpRequest();
				} else if (window.ActiveXObject) {// code for IE5, IE6
					this.xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
				}

				if (this.xmlhttp!=null)  {
					try {	
						this.xmlhttp.onreadystatechange=_cp_instances[this.obj_idx].handle_http_result;
						this.xmlhttp.open("GET",url,true);
						this.xmlhttp.setRequestHeader("Content-Type", "text/xml");
						this.xmlhttp.send(null);
					}
					catch(er) {
						this.disp_err('1202', er);
					}
				} else {
					this.disp_err('1203', 'this.xmlhttp==null');
				}
			}
		} else {
			this.disp_err('0002', 'invalid postcode format');
		}
	}

	this.validate_pc = function (dirty_pc) {
		// first strip out anything not alphanumenric
		var pc = '';
		do {
			pc = dirty_pc;
			dirty_pc = dirty_pc.replace(/[^A-Za-z0-9]/, "");
		} while (pc != dirty_pc);
		pc = dirty_pc.toUpperCase();
		// check if we have the right length with what is left
		if (7 >= pc.length && 5 <= pc.length) {
			// get the in code 
			var inc = pc.substring(pc.length-3,pc.length);
			// get the out code
			var outc = pc.substring(0, pc.length-3);
			// now validate both in and out codes
			if (true == /[CIKMOV]/.test(inc)) {
				return null;
			}
			// inCode must be NAA
			if ( '0' <= inc.charAt(0) && '9' >= inc.charAt(0) &&
				 'A' <= inc.charAt(1) && 'Z' >= inc.charAt(1) &&
				 'A' <= inc.charAt(2) && 'Z' >= inc.charAt(2) ) {
				// outcode must be one of AN, ANN, AAN, ANA, AANN, AANA
				switch (outc.length) { 
					case 2: // AN
						if ('A' <= outc.charAt(0) && 'Z' >= outc.charAt(0) &&
							'0' <= outc.charAt(1) && '9' >= outc.charAt(1) ) { return (pc); }
						break;
					case 3: // ANN, AAN, ANA
						if ('A' <= outc.charAt(0) && 'Z' >= outc.charAt(0)) {
							if ('0' <= outc.charAt(1) && '9' >= outc.charAt(1) &&
								'0' <= outc.charAt(2) && '9' >= outc.charAt(2) ) { return (pc); }
							else if ('A' <= outc.charAt(1) && 'Z' >= outc.charAt(1) &&
									 '0' <= outc.charAt(2) && '9' >= outc.charAt(2) ) { return (pc); }
							else if ('0' <= outc.charAt(1) && '9' >= outc.charAt(1) &&
									 'A' <= outc.charAt(2) && 'Z' >= outc.charAt(2) ) { return (pc); }
						}
						break;
					case 4: // AANN, AANA
						if ('A' <= outc.charAt(0) && 'Z' >= outc.charAt(0) &&
							'A' <= outc.charAt(1) && 'Z' >= outc.charAt(1) &&
							'0' <= outc.charAt(2) && '9' >= outc.charAt(2)) {
							if ('0' <= outc.charAt(3) && '9' >= outc.charAt(3) ) { return (pc); }
							else if ('A' <= outc.charAt(3) && 'Z' >= outc.charAt(3) ) { return (pc); }
						}
						break;
					default:
						break;
				}
			}
		}
		return null;
	}


	this.direct_xml_fetch = function(pc, key) {
		try	{
			var the_parent = document.getElementById(this.config.result_elem_id);

			var url = '';
			if ("https:" == document.location.protocol) {
				url = 'https://';
			} else {
				url = 'http://';
			}
			url += this.config.lookup_url+'?postcode='+pc+'&key='+key+'&obj_idx='+this.obj_idx;
			cs = document.createElement("script");
			cs.src = url;
			cs.type = "text/javascript";
			the_parent.appendChild(cs);
		}
		catch(er){
			this.disp_err('1206', er);
		};
	}

	this.handle_js_error = function (ef,em) {
		if ('7001' == ef) {
			if (0 != em.length) {
				this.disp_err_msg('demo limit reached, please use one of: '+em);
			} else {
				this.disp_err_msg("sorry, demo usage has a daily limit");
			}
		} else if ('8001' == ef) {
			this.disp_err(ef, 'invalid token format '+em);
		} else {
			this.disp_err(ef, 'server error code');
		}
	}

	this.handle_js_response = function (tn, cn, ln, rn, pn, on) {
		this.process_xml(tn, cn, ln, rn, pn, on, this.clean_pc);
	}

	this.lookup_timeout_err = function() {
		this.disp_err('9001', 'internal timeout after '+this.config.lookup_timeout+'ms')
	}
}

