var httpRoot = "http://www.tc-ps.com/";
function none(){
}

// querystring functions
function getQueryVariable(variable) {
  var query = window.location.search.substring(1);
  var vars = query.split("&");
  for (var i=0;i<vars.length;i++) {
    var pair = vars[i].split("=");
    if (pair[0] == variable) {
      return pair[1];
    }
  }
  return null;
}

function urlEncode(str){
	if (encodeURIComponent) {
	    return encodeURIComponent(str);
	} else {
	    return escape(str);
	}
}

function urlDecode(str){
	if (decodeURIComponent) {
	    return decodeURIComponent(str);
	} else {
	    return unescape(str);
	}
}

function utf8Encode(str){
  return unescape(encodeURIComponent(str));
}

function utf8Decode(str){
  return decodeURIComponent(escape(str));
}

String.prototype.stripHTMLTags = function(){

	return this.replace(/(<([^>]+)>)/ig," ");
}


function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		obj = obj.offsetParent;
		while (obj != null) {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
			obj = obj.offsetParent;
		}
	}
	return [curleft,curtop];
}

function getPageSizeObject(){

	var xScroll, yScroll;

	if (window.innerHeight && window.scrollMaxY) {
		xScroll = document.body.scrollWidth;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}

	var windowWidth, windowHeight;
	if (self.innerHeight) {	// all except Explorer
		windowWidth = self.innerWidth;
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}

	// for small pages with total height less then height of the viewport
	if(yScroll < windowHeight){
		pageHeight = windowHeight;
	} else {
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowWidth){
		pageWidth = windowWidth;
	} else {
		pageWidth = xScroll;
	}


	return {pageWidth:pageWidth,pageHeight:pageHeight,windowWidth:windowWidth,windowHeight:windowHeight};
}

function getYScroll(){


	var yScroll;

	if (self.pageYOffset) {
		yScroll = self.pageYOffset;
	} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
		yScroll = document.documentElement.scrollTop;
	} else if (document.body) {// all other Explorers
		yScroll = document.body.scrollTop;
	}

	return yScroll;

}

function setOpacity(obj, opacity) {
	if(typeof(obj) == "string"){
		obj = document.getElementById(obj);
	}
	obj.style.filter = "alpha(style=0,opacity:" + opacity + ")";	// IE
	obj.style.KHTMLOpacity = opacity / 100;						// Konqueror
	obj.style.MozOpacity = opacity / 100;							// Mozilla (old)
	obj.style.opacity = opacity / 100;							// Mozilla (new)
}

function changeOpacity(id, opacStart, opacEnd, millisec) {
    //speed for each frame
    var speed = Math.round(millisec / 100);
    var timer = 0;

    //determine the direction for the blending, if start and end are the same nothing happens
    if(opacStart > opacEnd) {
        for(i = opacStart; i >= opacEnd; i--){
            setTimeout("setOpacity('" + id + "'," + i + ")",(timer * speed));
            timer++;
        }
    } else if(opacStart < opacEnd) {
        for(i = opacStart; i <= opacEnd; i++){
            setTimeout("setOpacity('" + id + "'," + i + ")",(timer * speed));
            timer++;
        }
    }
}


function getStyle(obj,styleProp){

	if (obj.currentStyle)
		var y = obj.currentStyle[styleProp];

	else if (window.getComputedStyle)
		var y = document.defaultView.getComputedStyle(obj,null).getPropertyValue(styleProp);


	return y;
}

function clearDefault(el) {
  if (el.defaultValue==el.value) el.value = ""
}

function clearDropDown(OptionList) {

   // Always clear an option list from the last entry to the first
   for (x = OptionList.length; x >= 0; x--) {
      OptionList[x] = null;
   }
}


function addToDropDown(OptionList, OptionValue, OptionText, selected) {
   // Add option to the bottom of the list
   OptionList[OptionList.length] = new Option(OptionText, OptionValue, false, selected);
}


function numberFormat(num,decimalPlaces){
	decimalPlaces = (decimalPlaces == null) ? 2 : decimalPlaces;
	num = Math.round(num*Math.pow(10,decimalPlaces))/Math.pow(10,decimalPlaces);
	num = String(num);
	var decimals = null;

	if(num.indexOf(".") != -1){
		num = num.split(".");
		decimals = num[1];
		num = String(num[0]);
	}
	var str = "";
	var p;
	while(num.length > 3){
		str = ","+num.substr(num.length-3)+str;
		num = num.substr(0,num.length-3);
	}
	if(num.length > 0){
		str = num+str;
	}

	if(decimals){
		while(decimals.length < decimalPlaces){
			decimals += "0";
		}
		str = str + "." + decimals;

	}

	return str;

}

// JAVASCRIPT INCLUDE FUNCTIONS
// thanks to http://www.phpied.com/javascript-include/

function includeJS(script_filename) {
	document.write("<script language=\"JavaScript\" type=\"text/javascript\" src=\""+script_filename+"\"></script>\n");
}

function jsIncludeDom(script_filename) {
    var head = document.getElementsByTagName('head').item(0);
    var js = document.createElement('script');
    js.setAttribute('language', 'javascript');
    js.setAttribute('type', 'text/javascript');
    js.setAttribute('src', script_filename);
    head.appendChild(js);
    return false;
}

var jsIncludedFiles = new Array();

function jsIncludeOnce(script_filename,method) {
    if (!isInArray(script_filename, jsIncludedFiles)) {
        jsIncludedFiles[jsIncludedFiles.length] = script_filename;
        if(method == "dom"){
        	jsIncludeDom(script_filename);
        }else{
       		includeJS(script_filename);
        }
    }
}

function isInArray(needle, haystack) {
    for (var i = 0; i < haystack.length; i++) {
        if (haystack[i] == needle) {
            return true;
        }
    }
    return false;

}


function loadCSS(fileName,pos,ieCondition){

	var target = null;

	if (typeof ieCondition != "undefined") {
		var html = "[if "+ieCondition+"]>\n<link rel=\"stylesheet\" type=\"text/css\" href=\""+fileName+"\" />\n<![endif]";
		var fileRef = document.createComment(html);
	} else {
		var fileref = document.createElement("link");
		fileref.setAttribute("rel", "stylesheet");
		fileref.setAttribute("type", "text/css");
		fileref.setAttribute("href", fileName);
	}

	if(pos < 0){
		if(document.getElementsByTagName("head")[0].getElementsByTagName("link").length >= 0-pos){
			target = document.getElementsByTagName("head")[0].getElementsByTagName("link")[document.getElementsByTagName("head")[0].getElementsByTagName("link").length+pos];
		}
	}else if (pos>0){
		if (document.getElementsByTagName("head")[0].getElementsByTagName("link").length > pos+1) {
			target = document.getElementsByTagName("head")[0].getElementsByTagName("link")[pos + 1];
		}
	}
	if (target) {
		document.getElementsByTagName("head")[0].insertBefore(fileref, target);

	} else {
		document.getElementsByTagName("head")[0].appendChild(fileref);
	}
}

// JSON Display function

function displayJSONData(data){

	if(data.module.target != null){
		var element = document.getElementById(data.module.target);
		if(element != null){
			element.innerHTML = data.module.html;
			window.evalScripts(data.module.target);
		}

	}

}


// File system functions

function basename(path, suffix) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Ash Searle (http://hexmen.com/blog/)
    // +   improved by: Lincoln Ramsay
    // +   improved by: djmix
    // *     example 1: basename('/www/site/home.htm', '.htm');
    // *     returns 1: 'home'

    var b = path.replace(/^.*[\/\\]/g, '');

    if (typeof(suffix) == 'string' && b.substr(b.length-suffix.length) == suffix) {
        b = b.substr(0, b.length-suffix.length);
    }

    return b;
}


function dirname(path) {
    // http://kevin.vanzonneveld.net
    // +   original by: Ozh
    // +   improved by: XoraX (http://www.xorax.info)
    // *     example 1: dirname('/etc/passwd');
    // *     returns 1: '/etc'
    // *     example 2: dirname('c:/Temp/x');
    // *     returns 2: 'c:/Temp'
    // *     example 3: dirname('/dir/test/');
    // *     returns 3: '/dir'

    return path.replace(/\\/g,'/').replace(/\/[^\/]*\/?$/, '');
}


// CLASS INHERITANCE

// Inheritance method
if(!Function.inherits){
	Function.prototype.inherits = function(superclass) {
		var x = function() {};
		x.prototype = superclass.prototype;
		this.prototype = new x();
	}
}


// jsr_class.js
//
// JSONscriptRequest -- a simple class for making HTTP requests
// using dynamically generated script tags and JSON
//
// Author: Jason Levitt
// Date: December 7th, 2005
//
// A SECURITY WARNING FROM DOUGLAS CROCKFORD:
// "The dynamic <script> tag hack suffers from a problem. It allows a page 
// to access data from any server in the web, which is really useful. 
// Unfortunately, the data is returned in the form of a script. That script 
// can deliver the data, but it runs with the same authority as scripts on 
// the base page, so it is able to steal cookies or misuse the authorization 
// of the user with the server. A rogue script can do destructive things to 
// the relationship between the user and the base server."
//
// So, be extremely cautious in your use of this script.
//
//
// Sample Usage:
//
// <script type="text/javascript" src="jsr_class.js"></script>
// 
// function callbackfunc(jsonData) {
//      alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude + 
//            '  Longitude = ' + jsonData.ResultSet.Result[0].Longitude);
//      aObj.removeScriptTag();
// }
//
// request = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&
//            output=json&callback=callbackfunc&location=78704';
// aObj = new JSONscriptRequest(request);
// aObj.buildScriptTag();
// aObj.addScriptTag();
//
//


// Constructor -- pass a REST request URL to the constructor
//
function JSONscriptRequest(fullUrl) {
    // REST request path
    this.fullUrl = fullUrl; 
    // Keep IE from caching requests
    this.noCacheIE = '&noCacheIE=' + (new Date()).getTime();
    // Get the DOM location to put the script tag
    this.headLoc = document.getElementsByTagName("head").item(0);
    // Generate a unique script tag id
    this.scriptId = 'JscriptId' + JSONscriptRequest.scriptCounter++;
}

// Static script ID counter
JSONscriptRequest.scriptCounter = 1;

// buildScriptTag method
//
JSONscriptRequest.prototype.buildScriptTag = function () {

    // Create the script tag
    this.scriptObj = document.createElement("script");
    
    // Add script object attributes
    this.scriptObj.setAttribute("type", "text/javascript");
    this.scriptObj.setAttribute("charset", "utf-8");
    this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);
    this.scriptObj.setAttribute("id", this.scriptId);
	
}
 
// removeScriptTag method
// 
JSONscriptRequest.prototype.removeScriptTag = function () {
    // Destroy the script tag
    this.headLoc.removeChild(this.scriptObj);  
}

// addScriptTag method
//
JSONscriptRequest.prototype.addScriptTag = function () {
    // Create the script tag
    this.headLoc.appendChild(this.scriptObj);
}

/**
 * @author diccon
 */
function JSONSocketObject(httpRoot){

	this.httpRoot = httpRoot;

	this.jsonObjects = new Object();
	this.callbacks = new Object();

	this.globalVariable = "JSONSocket";


	this.makeCall = function(name,action,data,callback){

		var url = this.httpRoot+directoryIndex+"?action="+action;

		if(data != null){
			//url += "&data="+urlEncode(this.serialize(data));
			var dataStr = this.serialize(data);

			//alert(dataStr);

			dataStr = dataStr.replace( /\u2018/g, "'" );
			dataStr = dataStr.replace( /\u2019/g, "'" );
			dataStr = dataStr.replace( /\u201c/g, '\\\"' );
			dataStr = dataStr.replace( /\u201d/g, '\\\"' );
			dataStr = dataStr.replace( /\u2013/g, '-' );
			dataStr = dataStr.replace( /\u2014/g, '--' );
			dataStr = dataStr.replace( /\uFFFD/g, "'" );
			dataStr = dataStr.replace( /\u2026/g,"...");

			dataStr = escape(dataStr);

			var regex = /%0D%0A/g;
			dataStr = dataStr.replace(regex,"%5Cn");

			url += "&data="+dataStr;

			//alert(url);

		}


		if(callback != null){
			url += "&callback="+this.registerCallback(name,callback);
		}

		if(this.jsonObjects[name] != null){
			this.jsonObjects[name].removeScriptTag();
		}

		this.jsonObjects[name] = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.jsonObjects[name].buildScriptTag();
		// Add the script tag to the page
		this.jsonObjects[name].addScriptTag();
	}

	this.registerCallback = function(name,func){
		this.callbacks[name] = func;
		return this.globalVariable+".callbacks['"+name+"']";
	}

	// Javascript serialize - thanks http://blog.stchur.com/2007/04/06/serializing-objects-in-javascript/

	this.serialize = function(_obj){

		if(_obj == null){
			return null;
		}
	   // Let Gecko browsers do this the easy way
	   if (typeof _obj.toSource !== 'undefined' && typeof _obj.callee === 'undefined'){
	      return _obj.toSource();
	   }

	   // Other browsers must do it the hard way
	   switch (typeof _obj){
	      // numbers, booleans, and functions are trivial:
	      // just return the object itself since its default .toString()
	      // gives us exactly what we want
	      case 'number':
	      case 'boolean':
	      case 'function':
	         return _obj;
	         break;

	      // for JSON format, strings need to be wrapped in quotes
	      case 'string':
	         return '"' + _obj.replace(/"/g,'\\"') + '"';
	         break;

	      case 'object':
	         var str;
	         if (_obj.constructor === Array || typeof _obj.callee !== 'undefined'){
	            str = '[';
	            var i, len = _obj.length;
	            for (i = 0; i < len-1; i++) { str += this.serialize(_obj[i]) + ','; }
	            str += this.serialize(_obj[i]) + ']';
	         } else {
	            str = '{';
	            var key;
	            for (key in _obj) { str += key + ':' + this.serialize(_obj[key]) + ','; }
	            str = str.replace(/\,$/, '') + '}';
	         }
	         return str;
	         break;

	      default:
	         return 'UNKNOWN';
	         break;
	   }
	}

}


var JSONSocket = new JSONSocketObject(httpRoot);/* Object to connect to RPW server, perform searches and store JSON data */

function RPWSearchSocketObject(httpRoot){

	JSONSocketObject.call(this,httpRoot);

	this.globalVariable = "RPWSearchSocket";

	this.searchSettings = new Object();// associative array object to hold search settings

	this.sessionName = "propertysearch";

	this.onResultLoadAction = null;// method to call on result load.

	this.onSearchSettingsLoadAction = null;

	this.onSearchCompleteAction = null;

	this.onShortlistLoadAction = null;

	this.onSearchFormAttributesLoadAction = null;

	this.onUserPreferencesLoadAction = null;

	this.userPreferences = new Object();

	this.onSchoolsLoadAction = null;

	this.onStationsLoadAction = null;

	this.onOfficeLoadAction = null;

	this.resultSet = null;// object to hold result data

	this.resultTotal = 0;

	this.googleMapData = null;

	// JSON objects

	this.searchJsonObj = null;
	this.resultsJsonObj = null;
	this.settingsJsonObj = null;
	this.shortlistJsonObj = null;
	this.searchFormAttributesJsonObj = null;
	this.schoolsJsonObj = null;
	this.officeJsonObj = null;
	this.stationsJsonObj = null;
	this.preferencesJsonObj = null;

	// URL hooks

	this.searchURL = "index.php?action=propertysearchjson";
	this.resultsURL = "index.php?action=searchresultsjson";
	this.schoolsURL = "index.php?action=getschoolsjson";
	this.stationsURL = "index.php?action=getstationsjson";
	this.officesURL = "index.php?action=getofficesjson";
	this.searchSettingsURL = "index.php?action=getsearchsettingsjson";
	this.searchFormAttributesURL = "index.php?action=getsearchformattributesjson";

	// Search Methods

	this.doSearch = function(){

		this.resetData();

		var url = this.httpRoot+this.searchURL+"&sessionname="+this.sessionName;

		for(var i in this.searchSettings){

			if(this.searchSettings[i] != null){
				url += "&"+i+"="+escape(this.searchSettings[i]);
			}

		}

		url += "&callback=RPWSearchSocket.onSearchComplete";

		//alert(url);

		if(this.searchJsonObj != null){
			this.searchJsonObj.removeScriptTag();
		}

		this.searchJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.searchJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.searchJsonObj.addScriptTag();

	}

	this.resetData = function(){

		this.resultSet = null;
		this.resultTotal = 0;
		this.googleMapData = null;

	}

	this.onSearchComplete = function(data){

		this.resultTotal = data.resultTotal;

		if(this.onSearchCompleteAction != null){
			this.onSearchCompleteAction(data);
		}

	}

	this.getResultSet = function(offset,displayCount,callback,offices,schools){

		if(callback != null){
			this.onResultLoadAction = callback;
		}

		var url = this.httpRoot+this.resultsURL+"&sessionname="+this.sessionName+"&offset="+offset+"&displaycount="+displayCount+"&callback=RPWSearchSocket.onResultLoad";

		url += (offices) ? "&getoffices=true" : "";
		url += (schools) ? "&getschools=true" : "";

		if(this.resultsJsonObj != null){
			this.resultsJsonObj.removeScriptTag();
		}


		this.resultsJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.resultsJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.resultsJsonObj.addScriptTag();

	}

	this.onResultLoad = function(data){

		if(this.onResultLoadAction != null){
			this.onResultLoadAction(data);
		}

	}

	this.getResultTotal = function(){

		return this.resultTotal;

	}


	// SCHOOLS METHODS


	this.getSchools = function(lat1,lat2,lng1,lng2,callback){

		if(callback != null){
			this.onSchoolsLoadAction = callback;
		}

		var url = this.httpRoot+this.schoolsURL+"&lat1="+lat1+"&lat2="+lat2+"&lng1="+lng1+"&lng2="+lng2+"&callback=RPWSearchSocket.onSchoolsLoad";

		if(this.schoolsJsonObj != null){
			this.schoolsJsonObj.removeScriptTag();
		}


		this.schoolsJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.schoolsJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.schoolsJsonObj.addScriptTag();

	}

	this.onSchoolsLoad = function(data){

		if(this.onSchoolsLoadAction != null){
			this.onSchoolsLoadAction(data);
		}

	}

	// STATIONS METHODS


	this.getStations = function(lat1,lat2,lng1,lng2,callback){

		if(callback != null){
			this.onStationsLoadAction = callback;
		}

		var url = this.httpRoot+this.stationsURL+"&lat1="+lat1+"&lat2="+lat2+"&lng1="+lng1+"&lng2="+lng2+"&callback=RPWSearchSocket.onStationsLoad";

		if(this.stationsJsonObj != null){
			this.stationsJsonObj.removeScriptTag();
		}

		this.stationsJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.stationsJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.stationsJsonObj.addScriptTag();

	}

	this.onStationsLoad = function(data){

		if(this.onStationsLoadAction != null){
			this.onStationsLoadAction(data);
		}

	}
	// OFFICES METHODS


	this.getOffices = function(lat1,lat2,lng1,lng2,callback){

		if(callback != null){
			this.onOfficesLoadAction = callback;
		}

		var url = this.httpRoot+this.officesURL+"&lat1="+lat1+"&lat2="+lat2+"&lng1="+lng1+"&lng2="+lng2+"&callback=RPWSearchSocket.onOfficesLoad";

		if(this.officesJsonObj != null){
			this.officesJsonObj.removeScriptTag();
		}


		this.officesJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.officesJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.officesJsonObj.addScriptTag();

	}

	this.onOfficesLoad = function(data){

		if(this.onOfficesLoadAction != null){
			this.onOfficesLoadAction(data);
		}

	}

	// Setting Methods

	this.inputSearchSetting = function(inputObj){// method to accept input from form elements (eg INPUT, SELECT etc)

		var value;

		switch(inputObj.nodeName.toLowerCase()){
			case "input":
				switch(inputObj.type){
					case "checkbox":
						if(inputObj.checked){
							value = inputObj.value;
						}else{
							value = null;
						}
						this.setSearchSetting(inputObj.name,value);
						break;
					case "text":
						this.setSearchSetting(inputObj.name,inputObj.value);
					}
				break;
			case "select":
				var selectedArray = new Array();
				for (i=0; i<inputObj.options.length; i++) {
					if (inputObj.options[i].selected) {
						selectedArray.push(inputObj.options[i].value);
					}
				}
				selectedArray = (selectedArray.length > 0) ? selectedArray.join(",") : null;
				this.setSearchSetting(inputObj.name,selectedArray);
				break;
		}

	}

	this.getSearchSettings = function(){
		return this.searchSettings;
	}

	this.setSearchSetting = function(a,v){

		if(v == null && this.searchSettings[a] != null){
			delete this.searchSettings[a];
		}else{
			this.searchSettings[a] = v;
		}

	}

	this.getSearchSetting = function(a){

		return this.searchSettings[a];

	}

	this.clearSearchSettings = function(){

		this.searchSettings = new Object();

	}

	this.clearAreas = function(){
		for(var i in this.searchSettings){
			if(i.substr(0,8) == "area_str"){
				delete this.searchSettings[i];
			}
		}
	}

	this.loadSettings = function(){

		var url = this.httpRoot+this.searchSettingsURL+"&sessionname="+this.sessionName+"&searchtype="+this.getSearchSetting("searchtype");

		if(this.settingsJsonObj != null){
			this.settingsJsonObj.removeScriptTag();
		}

		url += "&callback=RPWSearchSocket.onSettingsLoad";

		this.settingsJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.settingsJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.settingsJsonObj.addScriptTag();

	}

	this.onSettingsLoad = function(data){

		if (data.searchtype == this.getSearchSetting("searchtype")) {

			for (i in data) {
				//if (i != "keywords") {
					this.setSearchSetting(i, data[i]);
				//}
			}

			if (data.resultTotal != null) {
				this.resultTotal = data.resultTotal;
			}

		}

		if(data.interestRate != null){
			this.setSearchSetting("interestRate",data.interestRate);
		}

		if(this.onSearchSettingsLoadAction != null){
			this.onSearchSettingsLoadAction(data);
		}
	}

	this.loadSearchFormAttributes = function(qString){

		var url = this.httpRoot+this.searchFormAttributesURL;

		if(this.searchFormAttributesJsonObj != null){
			this.searchFormAttributesJsonObj.removeScriptTag();
		}

		if(qString != null){
			url += "&"+qString;
		}

		url += "&callback=RPWSearchSocket.onSearchFormAttributesLoad";

		this.searchFormAttributesJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.searchFormAttributesJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.searchFormAttributesJsonObj.addScriptTag();

	}

	this.onSearchFormAttributesLoad = function(data){
		if(this.onSearchFormAttributesLoadAction != null){
			this.onSearchFormAttributesLoadAction(data);
		}
	}

	this.loadUserPreferences = function(callback){

		if(callback != null){
			this.onUserPreferencesLoadAction = callback;
		}

		var url = this.httpRoot+"index.php?action=getuserpreferencesjson";

		if(this.preferencesJsonObj != null){
			this.preferencesJsonObj.removeScriptTag();
		}

		url += "&callback=RPWSearchSocket.onUserPreferencesLoad";

		this.preferencesJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.preferencesJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.preferencesJsonObj.addScriptTag();

	}

	this.onUserPreferencesLoad = function(data){

		if(data != null && data.preferences != null){

			var j;
			for(var i in data.preferences){
				for (j in data.preferences[i]) {
					//alert(j+"="+data.preferences[i][j]);
					this.userPreferences[j] = data.preferences[i][j];
				}
			}
		}


		if(this.onUserPreferencesLoadAction != null){
			this.onUserPreferencesLoadAction(data);
		}

	}

	this.saveUserPreference = function(pref,val){

		//alert("save "+pref+" = "+val);

		this.userPreferences[pref] = val;

		var url = this.httpRoot+"index.php?action=saveuserpreferencejson";

		url += "&preference="+pref+"&value="+val;

		if(this.preferencesJsonObj != null){
			this.preferencesJsonObj.removeScriptTag();
		}

		url += "&callback=RPWSearchSocket.onUserPreferenceSave";

		this.preferencesJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.preferencesJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.preferencesJsonObj.addScriptTag();

	}

	this.getUserPreference = function(pref){
		if(this.userPreferences != null && this.userPreferences[pref] != null){
			return this.userPreferences[pref];
		}
		return null;
	}

	this.onUserPreferenceSave = function(data){

	}

	// WEBSTAT Methods

	this.saveWebStat = function(identifier,type){

		if (this.webStatURL != null) {

			type = (type == null) ? "d" : type;

			var url = this.httpRoot + this.webStatURL+"&property="+identifier+"&type="+type;

			url += "&callback=RPWSearchSocket.onWebStatSave";

			this.webStatJsonObj = new JSONscriptRequest(url);
			// Build the dynamic script tag
			this.webStatJsonObj.buildScriptTag();
			// Add the script tag to the page
			this.webStatJsonObj.addScriptTag();

		}
	}

	this.onWebStatSave = function(data){

	}

	// Shortlist methods

	this.saveShortlistToSession = function(shortlist,itemObject){

		var url = this.httpRoot+"index.php?action=savecartjson&cart="+shortlist+"&items=";

		for(var i in itemObject){

			url += (i > 0) ? "," : "";

			url += itemObject[i].db+"-"+itemObject[i].pcode;

		}


		url += "&callback=RPWSearchSocket.onShortlistSave";

		if(this.shortlistJsonObj != null){
			this.shortlistJsonObj.removeScriptTag();
		}

		this.shortlistJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.shortlistJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.shortlistJsonObj.addScriptTag();


	}

	this.onShortlistSave = function(dataObj){
		//alert("saved");
	}

	this.loadShortlist = function(shortlist,callback){

		if(callback != null){
			this.onShortlistLoadAction = callback;
		}

		var url = this.httpRoot+"index.php?action=getshortlistitemsjson&cart="+shortlist;

		url += "&callback=RPWSearchSocket.onShortlistLoad";

		if(this.shortlistJsonObj != null){
			this.shortlistJsonObj.removeScriptTag();
		}

		this.shortlistJsonObj = new JSONscriptRequest(url);
		// Build the dynamic script tag
		this.shortlistJsonObj.buildScriptTag();
		// Add the script tag to the page
		this.shortlistJsonObj.addScriptTag();


	}

	this.onShortlistLoad = function(dataObj){
		if(this.onShortlistLoadAction != null){
			this.onShortlistLoadAction(dataObj);
		}
	}


}

RPWSearchSocketObject.inherits(JSONSocketObject);

// create global instance of search socket object

var RPWSearchSocket = new RPWSearchSocketObject(httpRoot);

// Inheritance method
if(!Function.inherits){
	Function.prototype.inherits = function(superclass){
		var x = function(){
		};
		x.prototype = superclass.prototype;
		this.prototype = new x();
	}
}

// An HTML display object class encapsulating various methods to allow style manipulation and hierarchy tracking

function DisplayObject(domElement){

	this.domElement = domElement;// DOM object container;

	this.attributes = new Object();// Object to hold attributes.

	this.parentObj = null;// Object to hold parent DisplayObject

	this.opacity = 100;// default opacity

	this.transformations = new Array();// array to hold current list of
										// transformations
	this.transformationStarted = false;

	this.onTransformEndFunction = null;

	// Style Methods

	this.setClass = function(className){

		if (this.domElement != null) {
			this.domElement.className = className;
		}

	}

	this.setStyle = function(style, value){// method to set style of domElement (CSS styles e.g. border-width will be converted to javascript compatible).

		if(this.domElement != null){

			var pattern = /\-([a-z])/;

			while (String(style).match(pattern)){

				style = String(style).replace(pattern,
						String(RegExp.$1).toUpperCase());

			}

			this.domElement.style[style] = value;

		}

	}

	/*this.getStyle = function(style){

		if(this.domElement != null){

			var pattern = /\-([a-z])/;

			while (String(style).match(pattern)){

				style = String(style).replace(pattern,
						String(RegExp.$1).toUpperCase());

			}

			return this.domElement.style[style];

		}

		return null;

	}*/

	this.getStyle = function(strCssRule,domElement){

		if(!domElement){
			domElement = this.domElement;
		}

		var strValue = "";
		if(document.defaultView && document.defaultView.getComputedStyle){
			strValue = document.defaultView.getComputedStyle(domElement, "").getPropertyValue(strCssRule);
		}
		else if(domElement.currentStyle){
			strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
				return p1.toUpperCase();
			});
			strValue = domElement.currentStyle[strCssRule];
		}
		return strValue;
	}



	/// SIZE METHODS

	this.getWidth = function(domElement){
		if(domElement == null){
			domElement = this.domElement;
		}
		if (domElement != null) {
			if (domElement.style.pixelWidth) {
				return domElement.style.pixelWidth;
			}else if (domElement.offsetWidth){
				return domElement.offsetWidth;
			}else{
				return domElement.clientWidth;
			}
		}
		return null;
	}

	this.getHeight = function(domElement){
		if(domElement ==  null){
			domElement = this.domElement;
		}
		if (domElement != null) {
			if (domElement.style.pixelHeight) {
				return domElement.style.pixelHeight;
			}else if (domElement.offsetHeight){
				return domElement.offsetHeight;
			}else{
				return domElement.clientHeight;
			}
		}
		return null;
	}

	this.getPageSizeObject = function(){

		var xScroll, yScroll;

		if(window.innerHeight && window.scrollMaxY){
			xScroll = document.body.scrollWidth;
			yScroll = window.innerHeight + window.scrollMaxY;
		}else if(document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
			xScroll = document.body.scrollWidth;
			yScroll = document.body.scrollHeight;
		}else{ // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
			xScroll = document.body.offsetWidth;
			yScroll = document.body.offsetHeight;
		}

		var windowWidth, windowHeight;
		if(self.innerHeight){ // all except Explorer
			windowWidth = self.innerWidth;
			windowHeight = self.innerHeight;
		}else if(document.documentElement
				&& document.documentElement.clientHeight){ // Explorer 6 Strict Mode
			windowWidth = document.documentElement.clientWidth;
			windowHeight = document.documentElement.clientHeight;
		}else if(document.body){ // other Explorers
			windowWidth = document.body.clientWidth;
			windowHeight = document.body.clientHeight;
		}

		// for small pages with total height less then height of the viewport
		if(yScroll < windowHeight){
			pageHeight = windowHeight;
		}else{
			pageHeight = yScroll;
		}

		// for small pages with total width less then width of the viewport
		if(xScroll < windowWidth){
			pageWidth = windowWidth;
		}else{
			pageWidth = xScroll;
		}

		return {
			pageWidth : pageWidth,
			pageHeight : pageHeight,
			windowWidth : windowWidth,
			windowHeight : windowHeight
		};
	}

	this.getYScroll = function(){


		var yScroll;

		if (self.pageYOffset) {
			yScroll = self.pageYOffset;
		} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
			yScroll = document.documentElement.scrollTop;
		} else if (document.body) {// all other Explorers
			yScroll = document.body.scrollTop;
		}

		return yScroll;

	}

	// DOM element methods

	this.createDOMElement = function(tag, className){

		if(tag == null){
			tag = "div";
		}

		this.domElement = document.createElement(tag);

		if(className != null){
			this.domElement.className = className;

		}

		//this.domElement['displayObject'] = this;

	}

	this.setDOMElement = function(domElement){

		this.domElement = domElement;

	}

	this.getDOMElement = function(){

		return this.domElement;

	}

	this.setDOMAttribute = function(a, v){

		if(this.domElement != null){

			this.domElement.setAttribute(a, v);

		}

	}

	this.setID = function(id){

		this.setDOMAttribute("id", id);

	}

	this.setHTML = function(html){

		if(this.domElement != null){
			this.domElement.innerHTML = html;
		}

	}

	// Child methods

	this.addDisplayObject = function(tag){

		var displayObject = new DisplayObject();
		displayObject.setParent(this);
		displayObject.createDOMElement(tag);

		this.domElement.appendChild(displayObject.getDOMElement());

		return displayObject;

	}

	this.attachDisplayObject = function(displayObject){

		displayObject.setParent(this);

		this.domElement.appendChild(displayObject.getDOMElement());

		return displayObject;

	}

	this.addElement = function(tag, html){// method to add element. Arguments [2] onwards can be attribute pairs

		var element = document.createElement(tag);

		if(arguments.length > 2){

			for( var i = 2; i < arguments.length; i += 2){

				element.setAttribute(arguments[i], arguments[i + 1]);

			}

		}

		if(html != null){

			element.innerHTML = html;

		}

		this.domElement.appendChild(element);

		return element;

	}

	this.removeElement = function(element){

		this.domElement.removeChild(element);

	}

	this.addText = function(text){// method to add element.

		var textNode = document.createTextNode(text);

		this.domElement.appendChild(textNode);

		return textNode;

	}

	this.clearContents = function(){

		if(this.domElement != null){

			if(this.domElement.hasChildNodes()){
				while (this.domElement.childNodes.length >= 1){
					this.domElement.removeChild(this.domElement.firstChild);
				}
			}

		}
	}

	this.appendToElement = function(element){

		if(element != null && this.getDOMElement() != null){

			element.appendChild(this.getDOMElement());

		}

	}

	this.removeFromElement = function(element){

		if(element != null && this.getDOMElement() != null){

			element.removeChild(this.getDOMElement());

		}

	}

	this.appendChild = function(node){

		if(this.domElement != null){

			this.domElement.appendChild(node);

		}
	}

	// Parent methods

	this.getParent = function(){

		return this.parentObj;

	}

	this.setParent = function(parent){

		this.parentObj = parent;

	}

	// Settings methods

	this.setAttribute = function(attribute, value){

		this.attributes[attribute] = value;

	}

	this.getAttribute = function(attribute){

		if(this.attributes[attribute] != null){

			return this.attributes[attribute];

		}else if(this.parentObj != null){

			return this.parentObj.getAttribute(attribute);

		}

		return null;

	}

	// Transformation methods

	this.setOpacity = function(opacity,element){

		if (element == null) {
			this.opacity = opacity;
			element = this.domElement;
		}

		element.style.filter = "alpha(style=0,opacity:" + opacity + ")"; // IE
		if(opacity == 100 && element.style.removeAttribute != null){
			element.style.removeAttribute('filter');
		}
		element.style.KHTMLOpacity = opacity / 100; // Konqueror
		element.style.MozOpacity = opacity / 100; // Mozilla (old)
		element.style.opacity = opacity / 100; // Mozilla (new)
	}

	this.changeOpacity = function(newOpacity, increment){

		increment = (increment == null) ? 10 : increment;
		var i = 0;
		// determine the direction for the blending, if start and end are the
		// same nothing happens
		if(this.opacity > newOpacity){
			for( var o = this.opacity; o >= newOpacity; o -= increment){// add opacities to transformation array
				if(this.transformations[i] == null){
					this.transformations[i] = {
						opacity : o
					};// create new transformation object
				}else{
					this.transformations[i]["opacity"] = o;// add opacity to
															// existing
															// transformation
															// object
				}
				i++;
			}
		}else if(this.opacity < newOpacity){
			for( var o = this.opacity; o <= newOpacity; o += increment){
				if(this.transformations[i] == null){
					this.transformations[i] = {
						opacity : o
					};
				}else{
					this.transformations[i]["opacity"] = o;
				}
				i++;
			}
		}

		this.startTransform();
	}

	this.changeDimension = function(dimension, newValue, steps){

		steps = (steps == null) ? 10 : steps;

		var oldValue = (this.domElement.style[dimension] != null) ? parseInt(this.domElement.style[dimension]) : 0;

		var increment = (newValue-oldValue)/steps;

		for(var i=0;i<steps;i++){
			if(this.transformations[i] == null){
				this.transformations[i] = new Object();
			}
			this.transformations[i][dimension] = oldValue + increment*(i+1);
		}

		this.startTransform();
	}


	this.startTransform = function(){

		if(!this.transformationStarted){

		var thisObj = this;

		window.setTimeout( function(){thisObj.doTransformation()}, 50);

		this.transformationStarted = true;

		}

	}

	this.show = function(){

		this.setStyle("display", "block");

	}

	this.hide = function(){

		this.setStyle("display", "none");

	}

	this.hideElement = function(element){

		this.setElementDisplay(element, "none");

	}

	this.showElement = function(element){

		this.setElementDisplay(element, "block");

	}

	this.setElementDisplay = function(element, display){

		if(element != null){
			element.style.display = display;
		}
	}

	this.doTransformation = function(){

		if(this.transformations.length > 0){

			var transformation = this.transformations.shift();

			for( var i in transformation){
				switch(i){
				case "opacity":
					this.setOpacity(transformation[i]);
					break;
				case "left":
				case "right":
				case "top":
				case "bottom":
				case "width":
				case "height":
					this.setStyle(i, transformation[i]+"px");
					break;
				}
			}

			if(this.transformations.length > 0){
				var thisObj = this;
				window.setTimeout( function(){thisObj.doTransformation()}, 50);
			}else{
				this.transformationStarted = false;
				if(this.onTransformEndFunction != null){
					this.onTransformEndFunction(this);
				}
			}

		}

	}

	// listening methods

	this.addEventListener = function(event, func){

		if(this.domElement != null){

			this.domElement[event] = func;

		}

	}

	// Mouse methods

	this.getMousePosition = function(event){
		return {
			x : event.clientX,
			y : event.clientY
		};
	}

	this.getPosition = function(element){

		if (element == null) {
			element = this.domElement;
		}

		if (element != null) {

			var x = y = width = height = 0;

			if (element.style.pixelWidth) {
				width = element.style.pixelWidth;
				height = element.style.pixelHeight;
			} else
				if (element.offsetWidth) {
					width = element.offsetWidth;
					height = element.offsetHeight;
				} else {
					width = element.clientWidth;
					height = element.clientHeight;
				}

			if (element.offsetParent) {
				do {
					x += element.offsetLeft;
					y += element.offsetTop;
				} while (element = element.offsetParent);

			} else {
				return null;
			}

			return {
				x: x,
				y: y,
				width: width,
				height: height
			};

		}

		return null;

	}

}
// Inheritance method
if(!Function.inherits){
	Function.prototype.inherits = function(superclass){
		var x = function(){
		};
		x.prototype = superclass.prototype;
		this.prototype = new x();
	}
}

function FormObject(name, action, method){

	this.name = name;
	this.action = action;
	this.method = method;

	this.inputArray = new Array();
	this.hiddenFieldArray = new Array();

	// Inherit Display object
	DisplayObject.call(this);

	//

	this.FormObject = function(){

		this.createDOMElement("form");

		if(this.name){
			this.setDOMAttribute("name", this.name);
		}

		if(this.action){
			this.setDOMAttribute("action", this.action);
		}

		if(this.method){
			this.setDOMAttribute("method", this.method);
		}

		this.setDOMAttribute("accept-charset","UTF-8");

	}

	this.addTitle = function(text, tag){

		tag = (tag == null) ? "h3" : tag;

		var element = document.createElement(tag);

		var textNode = document.createTextNode(text);

		element.appendChild(textNode);

		this.domElement.appendChild(element);

		return element;

	}

	this.addHiddenField = function(name, value){

		var element = document.createElement("input");
		element.setAttribute("type", "hidden");
		element.setAttribute("name", name);
		if (value != null) {
			element.setAttribute("value", value);
		}

		this.domElement.appendChild(element);

		this.hiddenFieldArray.push(element);

		return element;

	}

	this.addLine = function(label, className, required){

		var line = new FormLineObject(label, className, required);
		line.displayContent();
		line.appendToElement(this.domElement);

		return line;

	}

	this.addTextField = function(name, label, value, className, required){

		var line = this.addLine(label, className, required);
		var element = new FormFieldElement(name, label, value, required);
		element.displayContent();
		element.appendToElement(line.domElement);
		element.setParent(this);

		this.inputArray.push(element);

		return element;

	}

	this.addMemoField = function(name, label, value, className, required){

		var line = this.addLine(label, className, required);
		var element = new MemoFieldElement(name, label, value, required);
		element.displayContent();
		element.appendToElement(line.domElement);
		element.setParent(this);

		this.inputArray.push(element);

		return element;

	}

	this.addCheckBox = function(name, label, value, checkedValue, className, required){

		var line = this.addLine(label, className, required);
		var element = new CheckBoxElement(name, label, value, checkedValue, required);
		element.displayContent();
		element.appendToElement(line.domElement);
		element.setParent(this);

		this.inputArray.push(element);

		return element;

	}

	this.addSelectField = function(name, label, value, values, labels, className, required){

		var line = this.addLine(label, className, required);
		var element = new SelectFieldElement(name, label, value, values, labels, required);
		element.displayContent();
		element.appendToElement(line.domElement);
		element.setParent(this);

		this.inputArray.push(element);

		return element;

	}

	this.addMultipleSelectField = function(name, label, value, values, labels, size, className){

		var line = this.addLine(label, className);
		var element = new MultipleSelectFieldElement(name, label, value, values, labels, size);
		element.displayContent();
		element.appendToElement(line.domElement);
		element.setParent(this);

		this.inputArray.push(element);

		return element;

	}

	this.addMultiSelectField = function(name, label, value, values, labels, fieldNamingConvention, className){

		var line = this.addLine(label, className);
		var element = new MultiSelectElement(name, label, value, values, labels, fieldNamingConvention);
		element.displayContent();
		element.appendToElement(line.domElement);
		element.setParent(this);

		this.inputArray.push(element);

		return element;

	}

	this.addUploadField = function(name, label, value, thumbnail, uploadFormURL, className){

		var line = this.addLine(label, className);
		var element = new UploadElement(name, label, value, thumbnail);
		element.displayContent();
		element.appendToElement(line.domElement);
		element.setParent(this);

		line.addUploader(uploadFormURL,element);

		this.inputArray.push(element);

		return element;

	}

	this.addMultiUploadField = function(name, label, existing, uploadFormURL, className){

		var line = this.addLine(label, className);
		var element = new UploadCollectionElement(name, label, existing);
		element.displayContent();
		element.appendToElement(line.domElement);
		element.setParent(this);

		line.addUploader(uploadFormURL,element);

		this.inputArray.push(element);

		return element;

	}

	this.addSubmitLine = function(label, onSubmitFunction, cancelFunction, cancelLabel){

		label = (label == null) ? "Submit" : label;

		cancelLabel = (cancelLabel == null) ? "Cancel" : cancelLabel;

		var element = new DisplayObject();
		element.createDOMElement("p", "formSubmit");

		if(cancelFunction != null){

			var cancelButton = document.createElement("input");
			cancelButton.setAttribute("type", "button");
			cancelButton.setAttribute("class", "button");
			cancelButton.setAttribute("className", "button");
			cancelButton.setAttribute("value", cancelLabel);
			cancelButton.onclick = cancelFunction;

			element.domElement.appendChild(cancelButton);
			element.domElement.appendChild(document.createTextNode(" "));

		}

		var submitButton = document.createElement("input");
		submitButton.setAttribute("type", "submit");
		submitButton.setAttribute("class", "button");
		submitButton.setAttribute("className", "button");
		submitButton.setAttribute("value", label);

		if(onSubmitFunction != null){
			submitButton.onclick = onSubmitFunction;
			this.domElement.onsubmit = function(){ return false;};
		}

		element.domElement.appendChild(submitButton);

		element.appendToElement(this.domElement);

		return element;

	}

	this.validate = function(){

		var errorStr = "";
		var article;
		var vowels = /^[aeiou]/i;

		for(i in this.inputArray){
			if(this.inputArray[i].required && (this.inputArray[i].getValue() == null || this.inputArray[i].getValue() == "")){

				article = (this.inputArray[i].labelString.match(vowels)) ? "an" : "a";

				errorStr += "Please supply "+article+" "+this.inputArray[i].labelString.toLowerCase()+"\n";

			}
		}

		if(errorStr != ""){
			alert(errorStr);
			return false;
		}

		return true;

	}

	this.getData = function(){

		var dataObject = new Object();

		for(var i in this.hiddenFieldArray){
			dataObject[this.hiddenFieldArray[i].name] = this.hiddenFieldArray[i].value;
		}

		for(i in this.inputArray){
			dataObject[this.inputArray[i].fieldName] = this.inputArray[i].getValue();
		}

		return dataObject;

	}

	this.FormObject();

}

FormObject.inherits(DisplayObject);





function FormLineObject(label,className, required){

	DisplayObject.call(this);

	this.labelString = label;
	this.required = required;

	this.formElementObject = null;

	className = (className == null) ? "formLine" : className;

	className += " "+label.replace(/\W/g,"");

	this.createDOMElement("p",className);

	// Label Methods

	this.appendLabel = function(){

		this.labelObject = this.getLabelElement();
		if(this.labelObject != null){
			this.domElement.appendChild(this.labelObject);
		}

	}

	this.removeLabel = function(){

		if(this.labelObject != null){

			this.domElement.removeChild(this.labelObject);
			this.labelObject = null;

		}

	}

	this.getLabelElement = function(){

		if (this.labelString != null) {

			var element = document.createElement("strong");
			element.innerHTML = this.labelString;

			if(this.required == true){
				element.innerHTML += "*";
			}

			return element;

		}

		return null;

	}

	this.addFormElementObject = function(element){
		this.formElementObject = element;
	}

	this.displayContent = function(){
		this.clearContents();
		this.appendLabel();
		if(this.formElementObject != null){
			this.formElementObject.displayContent();
			this.domElement.appendChild(this.formElementObject.domElement);
		}
	}

	this.clearContents = function(){
		this.removeLabel();
	}

	this.addUploader = function(uploadFormURL,targetObj){

		// register callback

		CallBackRegistry.registerFunction("FormField"+targetObj.fieldName,function(data){targetObj.onFileUpload(data)});

		var src = pathToRoot + unescape(uploadFormURL)+"&_setting="+targetObj.fieldName+"&_callback=parent.CallBackRegistry.call('FormField"+targetObj.fieldName+"')";

		var height;
		var className = "uploadFrame";

		if (String(uploadFormURL).indexOf("showsaveoptions") != -1) {
			height = "58";
			className += " options";
		}else{
			height = "34";
		}

		//alert(height);

		this.addElement("iframe",null,"class",className,"src",src,"width","475","height",height,"frameBorder","0","scrolling","no");

	}

}


FormLineObject.inherits(DisplayObject);

// Generic Text Box

function FormFieldElement(fieldName, label, storedValue, required){// generic form
	// element (text
	// input with label)

	this.fieldName = fieldName;
	this.labelString = label;
	this.required = (required == true) ? true : false;

	if(storedValue != null){
		this.storedValue = unescape(storedValue);
	}

	// Inherit Display object
	DisplayObject.call(this);

	// sub units

	this.labelObject = null;
	this.inputObject = null;

	this.onChangeListener = null;// container for onchange function

	this.getValue = function(){

		if(this.inputObject != null){

			return this.inputObject.value;

		}

		return null;

	}

	this.setValue = function(value){

		if(this.inputObject != null){

			this.inputObject.value = value;

		}

		this.storeValue();

	}

	this.storeValue = function(){

		this.storedValue = this.getValue();

	}

	this.disable = function(col){

		if(this.inputObject != null){
			this.inputObject.disabled = "disabled";
		}

		if(this.domElement != null){
			this.domElement.className = "formLine disabled";
		}

	}

	this.enable = function(){

		if(this.inputObject != null){
			this.inputObject.disabled = null;
		}

		if(this.domElement != null){
			this.domElement.className = "formLine";
		}
	}

	// Default value

	this.getStoredValue = function(){// method to return default value

		/*
		 * var val;
		 *
		 * if(RPWSearchSocket != null){ val =
		 * RPWSearchSocket.getSearchSetting(this.fieldName); if(val != null){
		 * return val; } }
		 */

		return this.storedValue;

	}

	// Content Creation

	this.displayContent = function(){

		var oldElement = null;
		if(this.domElement != null && this.domElement.parentNode != null){
			var oldElement = this.domElement;
		}

		this.createInput();

		if(oldElement != null){
			oldElement.parentNode.insertBefore(this.domElement, oldElement);
			oldElement.parentNode.removeChild(oldElement);
		}

	}

	this.clearContents = function(){

		this.removeInput();

	}

	this.setInputWidth = function(w){

		if(this.inputObject != null){

			this.inputObject.style.width = w + "px";

		}

	}

	// Input methods

	this.createInput = function(){

		this.inputObject = this.getInputElement();
		if(this.inputObject != null){
			this.domElement = this.inputObject;
		}

	}

	this.removeInput = function(){

		if(this.inputObject != null){

			this.domElement.parentNode.removeChild(this.domElement);
			this.inputObject = null;

		}

	}

	this.getInputElement = function(){

		var element = document.createElement("input");
		element.setAttribute("name", this.fieldName);
		element.setAttribute("class", "textbox");
		element.setAttribute("className", "textbox");

		var val = this.getStoredValue();

		if(val != null){
			element.setAttribute("value", utf8Decode(val));
		}

		var thisObj = this;
		element.onchange = function(){ thisObj.onChange(this) };

		element.onkeypress = function(e){
			// look for window.event in case event isn't passed in
			if (window.event) { e = window.event; }
			if (e.keyCode == 13){
				thisObj.onChange(this);
				//this.blur();
			}
        }


		return element;

	}

	this.setOnChangeListener = function(f){

		this.onChangeListener = f;

	}

	this.onChange = function(element){

		this.storeValue();

		if(this.onChangeListener != null){

			this.onChangeListener(element,this);

		}

	}

	this.focus = function(){
		if(this.inputObject != null){
			this.inputObject.focus();
		}
	}

	this.reset = function(){
		if(this.inputObject != null){
			this.inputObject.value = "";
			this.storedValue = null;
		}
	}


}

FormFieldElement.inherits(DisplayObject);

// Memo box

function MemoFieldElement(fieldName, label, storedValue, required){

	FormFieldElement.call(this, fieldName, label, storedValue, required);

	this.getInputElement = function(){

		var element = document.createElement("textarea");
		element.setAttribute("name", this.fieldName);
		element.setAttribute("class", "textbox");

		var val = this.getStoredValue();

		if(val != null){
			element.value = utf8Decode(val);
		}

		var thisObj = this;
		element.onchange = function(){thisObj.onChange(this) };

		return element;

	}

}

MemoFieldElement.inherits(FormFieldElement);

// Checkbox

function CheckBoxElement(fieldName, label, storedValue, fieldValue, required){

	FormFieldElement.call(this, fieldName, label, storedValue, required);

	this.fieldValue = (fieldValue == null) ? 1 : fieldValue;

	if(storedValue != null){
		this.storedValue = storedValue;// true or false
	}

	this.getInputElement = function(){

		var ieElement = "<input type=\"checkbox\" name=\"" + this.fieldName
				+ "\" value=\"1\"";
		ieElement += (this.getStoredValue()) ? " checked=\"checked\"" : "";
		ieElement += " />";

		try{
			var element = document.createElement(ieElement);
		}catch (e){
			var element = document.createElement("input");
			element.setAttribute("name", this.fieldName);
			element.setAttribute("type", "checkbox");
			element.setAttribute("value", this.fieldValue);

			if(this.getStoredValue() == true){
				element.checked = true;
			}
		}

		var thisObj = this;
		element.onclick = function(){
			thisObj.onChange(this)
		};

		return element;

	}

	this.getValue = function(){

		if(this.inputObject != null){

			return (this.inputObject.checked) ? this.fieldValue : 0;

		}

		return null;

	}

	this.reset = function(){
		if (this.inputObject != null) {
			this.inputObject.checked = false;
		}
	}

}

CheckBoxElement.inherits(FormFieldElement);

// Select Drop-down List

function SelectFieldElement(fieldName, label, storedValue, options, optionLabels, required){// extends FormFieldElement to provide drop-down list

	FormFieldElement.call(this, fieldName, label, storedValue, required);

	if(options != null){
		if(typeof options == "string"){
			this.options = options.split(",");
		}else{
			this.options = options;
		}
	}

	if(optionLabels != null){
		if(typeof optionLabels == "string"){
			this.optionLabels = optionLabels.split(",");
		}else{
			this.optionLabels = optionLabels;
		}
	}

	this.setOptions = function(options, optionLabels){

		if(options != null){
			if(typeof options == "string"){
				this.options = options.split(",");
			}else{
				this.options = options;
			}
		}

		if(optionLabels != null){
			if(typeof optionLabels == "string"){
				this.optionLabels = optionLabels.split(",");
			}else{
				this.optionLabels = optionLabels;
			}
		}

	}

	this.getValue = function(){

		if(this.inputObject != null){

			return this.inputObject.options[this.inputObject.selectedIndex].value;

		}

		return null;

	}

	this.setValue = function(value){

		if(this.inputObject != null){

			for(i in this.inputObject.options){

				if(this.inputObject.options[i].value == value){

					this.inputObject.selectedIndex = i;
					break;
				}
			}

		}

	}

	this.getInputElement = function(){

		if(this.options != null){

			var element = document.createElement("select");
			element.setAttribute("name", this.fieldName);
			if(this.isMulti){
				element.setAttribute("multiple", "multiple");
				element.setAttribute("size", this.size);
			}

			var option;
			var label;

			for( var i in this.options){

				option = document.createElement("option");
				option.setAttribute("value", this.options[i]);

				if(this.valueIsSelected(this.options[i])){

					option.setAttribute("selected", "selected");

				}


				label = (this.optionLabels == null || this.optionLabels[i] == null) ? this.options[i] : this.optionLabels[i];

				option.setAttribute("title",label);

				option.innerHTML = label;

				element.appendChild(option);

			}

			var thisObj = this;
			element.onchange = function(){ thisObj.onChange(this) };

			return element;

		}

		return null;

	}

	this.valueIsSelected = function(value){
		return (value == this.getStoredValue());
	}

	this.reset = function(){
		if (this.inputObject != null) {
			this.inputObject.selectedIndex = 0;
		}
		this.storedValue = null;
	}

}

SelectFieldElement.inherits(FormFieldElement);

function MultipleSelectFieldElement(fieldName, label, storedValue, options, optionLabels, size){// extends FormFieldElement to provide multi-select list

	SelectFieldElement.call(this, fieldName, label, storedValue, options, optionLabels);

	this.size = (size == null) ? Math.min(6,this.options.length) : size;

	this.isMulti = true;

	this.valueIsSelected = function(value){
		var regex = new RegExp("(^|\b)"+value+"(\b|$)","g");
		return regex.test(String(this.getStoredValue()));
	}

	this.getValue = function(){

		if(this.inputObject != null){

			var arr = new Array();

			for(var i in this.inputObject.options){
				if(this.inputObject.options[i] != null && this.inputObject.options[i].selected){
					arr.push(this.inputObject.options[i].value);
				}
			}

			if(arr.length > 0){
				return arr.join(",");
			}

		}

		return null;

	}

	this.setValue = function(value){

		this.storedValue = value;

		if(this.inputObject != null){

			for(var i in this.inputObject.options){
				if(this.valueIsSelected(this.inputObject.options[i].value)){
					this.inputObject.options[i].selected = true;
				}
			}

			if(arr.length > 0){
				return arr.join(",");
			}

		}

		return null;

	}

	this.reset = function(){
		if(this.inputObject != null){
			for(var i in this.inputObject.options){
				this.inputObject.options[i].selected = false;
			}
		}
		this.storedValue = null;
	}

}

MultipleSelectFieldElement.inherits(SelectFieldElement);


// Multiple checkboxes

function MultiSelectElement(fieldName, label, storedValue, options, optionLabels, fieldNamingConvention){// extends FormFieldElement to provide mulitple check boxes

	FormFieldElement.call(this, fieldName, label, storedValue);

	this.checkboxArr = new Array();

	this.fieldNamingConvention = (fieldNamingConvention == null) ? "array" : fieldNamingConvention;

	if(options != null){
		if(typeof options == "string"){
			this.options = options.split(",");
		}else{
			this.options = options;
		}
	}

	if(optionLabels != null){
		if(typeof optionLabels == "string"){
			this.optionLabels = optionLabels.split(",");
		}else{
			this.optionLabels = optionLabels;
		}
	}

	this.getValue = function(){

		if(this.checkboxArr != null){

			var selected = "";

			for( var i in this.checkboxArr){

				if(this.checkboxArr[i].checked){

					selected += (selected == "") ? "" : ",";
					selected += this.checkboxArr[i].value;

				}

			}

			return selected;

		}

		return null;

	}

	this.getSelectedValues = function(){

		if(this.checkboxArr != null){

			var selectedArr = new Array();

			for( var i in this.checkboxArr){

				if(this.checkboxArr[i].checked){

					selectedArr.push(this.checkboxArr[i].value);

				}

			}

			return (selectedArr.length > 0) ? selectedArr : null;

		}

		return null;
	}

	this.setValue = function(value){

		if(this.inputObject != null){

			for(i in this.inputObject.options){

				if(this.inputObject.options[i].value == value){

					this.inputObject.selectedIndex = i;
					break;
				}
			}

		}

	}

	this.isStoredValue = function(value){

		var selected = this.getStoredValue();

		var regex = new RegExp("(^|,)" + value + "(,|$)", "i");
		return regex.test(selected);

	}

	this.getInputElement = function(){

		if(this.options != null){

			this.checkboxArr = new Array();

			var element = document.createElement("div");

			var span;
			var checkbox;
			var label;
			var labelStr;
			var ieElement;
			var br;
			var fieldSuffix;
			var fieldValue;

			var thisObj = this;


			for(var i in this.options){

				if(this.options.constructor.toString().indexOf("Array") != -1){
					fieldValue = this.options[i];
					labelStr = (this.optionLabels == null || this.optionLabels[i] == null) ? this.options[i]	: this.optionLabels[i];
				}else{
					fieldValue = i;
					labelStr = this.options[i];
				}

				fieldSuffix = (this.fieldNamingConvention == "ordinal") ? i : "[]";

				ieElement = "<input type=\"checkbox\" name=\"" + this.fieldName + fieldSuffix+"\" value=\"" + fieldValue + "\"";
				ieElement += (this.isStoredValue(this.options[i])) ? " checked=\"checked\""
						: "";
				ieElement += " />";

				try{
					checkbox = document.createElement(ieElement);
				}catch (e){
					checkbox = document.createElement("input");
					checkbox.setAttribute("name", this.fieldName + fieldSuffix);
					checkbox.setAttribute("type", "checkbox");
					checkbox.setAttribute("value", fieldValue);

					if(this.isStoredValue(fieldValue)){
						checkbox.checked = true;
					}
				}

				checkbox.onclick = function(){
					thisObj.onChange(this)
				};

				span = document.createElement("span");

				span.appendChild(checkbox);

				this.checkboxArr.push(checkbox);

				label = document.createTextNode(labelStr);

				span.appendChild(label);

				element.appendChild(span);

				br = document.createElement("br");

				element.appendChild(br);

			}

			return element;

		}

		return null;

	}

	this.reset = function(){
		for(var i in this.checkboxArr){
			this.checkboxArr[i].checked = false;
		}
		this.storedValue = null;
	}

}

MultiSelectElement.inherits(FormFieldElement);


//File Upload

function UploadElement(fieldName, label, value, thumbnail){// extends FormFieldElement to creat file uploader

	FormFieldElement.call(this, fieldName, label, value);

	this.hiddenInput = null;
	this.imageInput = null;
	this.thumbnail = urlDecode(thumbnail);

	// Content Creation

	this.displayContent = function(){

		this.clearContents();

		this.createInput();

	}

	this.getInputElement = function(){

		var inputGroup = document.createElement("div");

		inputGroup.setAttribute("class","fileCollection");

		var thisObj = this;

		// add existing image

		if(this.storedValue != null){

			var imageInput = document.createElement("input");
			imageInput.setAttribute("type", "image");
			imageInput.setAttribute("value", (this.storedValue));
			imageInput.setAttribute("title", (this.storedValue));
			imageInput.setAttribute("name", this.fieldName+"Image");
			imageInput.setAttribute("src", (this.thumbnail));
			//imageInput.setAttribute("src",pathToRoot+directoryIndex+"?action=getmodulefilethumbnail&"+this.moduleIdentifier+"&setting="+this.fieldName+"&file="+this.storedImage+"&width=50&height=50&quality=80&crop=1");

			imageInput.onmousedown = function(event){ thisObj.showContextMenu(event, this) };
			imageInput.onclick = function(event){ return false; };

			inputGroup.appendChild(imageInput);

			this.imageInput = imageInput;

		}

		this.hiddenInput = document.createElement("input");
		this.hiddenInput.setAttribute("type","hidden");
		this.hiddenInput.setAttribute("name",this.fieldName);
		this.hiddenInput.setAttribute("value",this.storedValue)

		inputGroup.appendChild(this.hiddenInput);

		return inputGroup;

	}

	this.showContextMenu = function(event, item){

		var thisObj = this;

		var deleteFunction = function(){ thisObj.deleteItem(item);ContextMenu.removeMenu(); };

		ContextMenu.createMenu(event, "Delete", deleteFunction);

	}

	this.deleteItem = function(item){

		this.hiddenInput.value = "";

		this.inputObject.removeChild(item);

		this.imageInput = null;
	}

	this.onFileUpload = function(data){

		if(data.files == null || data.moduleIdentifier == null){
			return null;
		}

		var files = data.files;

		var fileArray = files.split(",");


		var thisObj = this;

		if(this.inputObject != null){
			// see if we have any files left - add them if we do.
			if(fileArray.length > 0){
				if(this.imageInput == null){
					var input;
					input = document.createElement("input");
					input.setAttribute("type","image");
					input.setAttribute("name",this.fieldName+"Image");
					input.onmousedown = function(event){ thisObj.showContextMenu(event, this) };
					input.onclick = function(event){ return false; };
					this.inputObject.appendChild(input);
					this.imageInput = input
				}
				this.imageInput.setAttribute("value",fileArray[0]);
				this.imageInput.setAttribute("src",pathToRoot+directoryIndex+"?action=getmodulefilethumbnail&"+unescape(data.moduleIdentifier)+"&setting="+this.fieldName+"&file="+fileArray[0]+"&width=50&height=50&quality=80&crop=1");
				this.imageInput.setAttribute("title",fileArray[0]);

				this.hiddenInput.value = fileArray[0];
			}

		}
	}


}

UploadElement.inherits(FormFieldElement);

// File Collection

function UploadCollectionElement(fieldName, label, existing){// extends FormFieldElement to creat file uploader

	FormFieldElement.call(this, fieldName, label, null);

	if(existing != null){
		this.inputArray = existing;
	}else{
		this.inputArray = new Array();
	}
	this.deletedItems = new Array();

	this.hiddenInput = null;

	// Content Creation

	this.displayContent = function(){

		this.clearContents();

		this.createInput();

	}

	this.getInputElement = function(){

		var inputGroup = document.createElement("div");

		inputGroup.setAttribute("class","fileCollection");

		var thisObj = this;

		// add existing images

		var fileList = "";

		for( var i = 0; i < this.inputArray.length; i++){

			var imageInput = document.createElement("input");
			imageInput.setAttribute("type", "image");
			imageInput.setAttribute("value", urlDecode(this.inputArray[i].file));
			imageInput.setAttribute("title", urlDecode(this.inputArray[i].file));
			imageInput.setAttribute("name", this.fieldName + "[]");
			imageInput.setAttribute("src", urlDecode(this.inputArray[i].thumbnail));

			imageInput.onmousedown = function(event){ thisObj.showContextMenu(event, this) };
			imageInput.onclick = function(event){ return false; };

			this.inputArray[i].domElement = imageInput;

			inputGroup.appendChild(imageInput);

			fileList += (fileList == "") ? "" : ",";
			fileList += urlDecode(this.inputArray[i].file);

		}

		this.hiddenInput = document.createElement("input");
		this.hiddenInput.setAttribute("type","hidden");
		this.hiddenInput.setAttribute("name",this.fieldName);
		this.hiddenInput.setAttribute("value",fileList)

		inputGroup.appendChild(this.hiddenInput);

		return inputGroup;

	}


	this.showContextMenu = function(event, item){

		var thisObj = this;

		var deleteFunction = function(){ thisObj.deleteItem(item);ContextMenu.removeMenu(); };

		ContextMenu.createMenu(event, "Delete", deleteFunction);

	}

	this.deleteItem = function(item){

		this.deletedItems.push(item.value);

		var fileArray = this.hiddenInput.value.split(",");

		for(var i=0;i<fileArray.length;i++){

			if(fileArray[i] == item.value){
				fileArray.splice(i,1);
			}

		}

		var fileList = "";
		for(var i=0;i<fileArray.length;i++){

			fileList += (fileList == "") ? "" : ",";
			fileList += fileArray[i];

		}
		this.hiddenInput.value = fileList;


		this.inputObject.removeChild(item);
	}

	this.onFileUpload = function(data){

		//alert(data.toSource());

		if(data.files == null || data.moduleIdentifier == null){
			return null;
		}

		var files = data.files;

		var fileArray = files.split(",");

		// loop through files, removing entries for those we've deleted

		for(var i=0;i<fileArray.length;i++){
			if(isInArray(fileArray[i],this.deletedItems)){// item has been deleted
				fileArray.splice(i,1);
			}
		}

		var thisObj = this;
		if(this.inputObject != null){
			// loop through existing inputs to see if they're still wanted - if not, delete them
			var fileFound;
			var fileList = "";

			if(this.inputObject.hasChildNodes()){
				inputs = this.inputObject.childNodes;
				for(i=0; i<inputs.length;i++){
					if(typeof(inputs[i].nodeName) != "undefined" && inputs[i].nodeName.toLowerCase() == "input" && inputs[i] != this.hiddenInput){

						fileFound = false;

						for(var j=0;j<fileArray.length;j++){// loop through list of files,
							if(fileArray[j] == String(inputs[i].value)){
								fileFound = true;
								fileList += (fileList == "") ? "" : ",";
								fileList += fileArray[j];
								fileArray.splice(j,1);
								break;
							}
						}

						if(!fileFound){// delete input from display

							inputs[i].parentNode.removeChild(inputs[i]);

							i--;

						}
					}
					inputs = this.inputObject.childNodes;
				}
			}
			// see if we have any files left - add them if we do.
			if(fileArray.length > 0){
				var input;
				for(i in fileArray){
					input = document.createElement("input");
					input.setAttribute("type","image");
					input.setAttribute("name",this.fieldName+"[]");
					input.setAttribute("value",fileArray[i]);
					input.setAttribute("src",pathToRoot+directoryIndex+"?action=getmodulefilethumbnail&"+unescape(data.moduleIdentifier)+"&setting="+this.fieldName+"&file="+fileArray[i]+"&width=50&height=50&quality=80&crop=1");
					input.setAttribute("title",fileArray[i]);
					input.onmousedown = function(event){ thisObj.showContextMenu(event, this) };
					input.onclick = function(event){ return false; };
					this.inputObject.appendChild(input);
					fileList += (fileList == "") ? "" : ",";
					fileList += fileArray[i];
				}
			}

			this.hiddenInput.value = fileList;
		}

	}


}

UploadCollectionElement.inherits(FormFieldElement);



function OverlayObject(container){

	DisplayObject.call(this);

	this.zIndex = 1000;
	this.containerObj = null;
	this.opacity = 80;
	this.color = "#000";
	this.removeOnClick = true;

	this.onRemoveFunction = null;

	if(container != null){
		this.containerObj = container;
	}

	this.OverlayObject = function(){

		this.createDOMElement("div","DTDOverlay");
		this.setStyle("position","absolute");

	}

	this.displayContent = function(){

		this.setStyle("top", "0");
		this.setStyle("left", "0");
		this.setStyle("z-index", this.zIndex);
		this.setStyle("width", "100%");
		this.setStyle("height", "100%");
		this.setStyle("display", 'block');
		this.setStyle("background-color", this.color);
		this.setOpacity(this.opacity);


		if(this.containerObj == null){// container is body, create full size with click off function
			this.containerObj = document.getElementsByTagName("body").item(0);
			this.addOnClickRemove();
			var pageSizes = this.getPageSizeObject();
			this.setStyle("height",pageSizes.pageHeight+"px");
		}else{
			this.setStyle("width",this.containerObj.clientWidth+"px");
			this.setStyle("height",this.containerObj.clientHeight+"px");
		}

		if(this.containerObj.firstChild != null){
			this.containerObj.insertBefore(this.domElement, this.containerObj.firstChild);
		}else{
			this.containerObj.appendChild(this.domElement);
		}


	}

	this.onUserClick = function(e){
		if(this.onRemoveFunction != null){

			this.onRemoveFunction(e);

		}else{
			if(this.removeOnClick){
				this.remove();
			}
		}
	}

	this.addOnClickRemove = function(){

		var thisObj = this;
		this.addEventListener("onclick", function(e){
			thisObj.onUserClick(e);
			return false;
		});

	}

	this.remove = function(){

		this.clearContents();

		this.containerObj.removeChild(this.domElement);

	}

	this.setContainer = function(container){
		this.containerObj = container;
	}

	this.OverlayObject();

}



OverlayObject.inherits(DisplayObject);// CONTEXT MENU METHODS


function LoadingGraphicObject(){

	DisplayObject.call(this);

	this.LoadingGraphicObject = function(){
	
		this.createDOMElement("div");
		this.setStyle("position","relative");

	}
	
	this.displayContent = function(){
		var background = this.addDisplayObject("div");
		background.setStyle("background","#FFF");
		background.setStyle("width","100%");
		background.setStyle("height","100%");
		background.setOpacity(80);
		
		var textElement = this.addDisplayObject("div");
		textElement.setStyle("position","absolute");
		textElement.addElement("p","Loading . . .");
		textElement.setStyle("font-family","Verdana, sans-serif");
		textElement.setStyle("color","#666");
		textElement.setStyle("font-weight","bold");
		textElement.setStyle("font-size","10px");
		textElement.setStyle("width","120px");
		textElement.setStyle("text-align","center");
		textElement.setStyle("padding-top","32px");
		textElement.setStyle("left",((parseInt(this.getStyle("width"))/2)-60)+"px");
		textElement.setStyle("top",((parseInt(this.getStyle("height"))/2)-40)+"px");
		textElement.setStyle("background","url("+httpRoot+"images/js-loading-icon.gif) top center no-repeat");
		
	}

	this.LoadingGraphicObject();

}



LoadingGraphicObject.inherits(DisplayObject);
// Object to display tabs linked to other display objects

function TabSetObject(){

	DisplayObject.call(this);

	this.tabSet = new Array();
	this.tabButtonArray = new Array();
	this.selectedIndex = 0;

	this.TabSetObject = function(){

		this.createDOMElement("div","TabSet");

	}


	this.addTab = function(title,displayObject,active,onclickFunc){

		this.tabSet.push({title:title,displayObject:displayObject,active:((active == false || active == null) ? false : true)});

		display = (active == false || active == null) ? "none" : "block";

		displayObject.setStyle("display",display);

		var tab;
		var thisObj = this;

		tab = this.addElement("a",title,"href","javascript:void(0);","title",title);
		tab.setAttribute("index",this.tabButtonArray.length);

		if(active == true){
			tab.className = "active";
		}

		tab.onclick	= (onclickFunc != null) ? function(){ thisObj.selectTab(this); onclickFunc(this); this.blur();} : function(){thisObj.selectTab(this); this.blur();};

		this.tabButtonArray.push(tab);
		this.domElement.appendChild(document.createTextNode(" "));

		return tab;

	}


	this.displayContent = function(){

		/*this.clearContents();

		var tab;
		var thisObj = this;

		for(var i=0; i<this.tabSet.length;i++){

			if(i>0){
				this.domElement.appendChild(document.createTextNode(" "));
			}

			tab = this.addElement("a",this.tabSet[i].title,"href","javascript:void(0);");
			tab.setAttribute("index",i);

			if(this.tabSet[i].active){
				tab.className = "active";
			}

			tab.onclick	= function(){thisObj.selectTab(this)};

			this.tabButtonArray.push(tab);

		}*/


	}

	this.selectTab = function(tab){

		var ind = tab.getAttribute("index");

		this.selectedIndex = ind;

		var display;

		var regex = / ?active/;


		for(var i=0; i<this.tabSet.length;i++){

			this.tabSet[i].active = (i==ind);

			if(i == ind){
				if(!regex.test(this.tabButtonArray[i].className)){
					this.tabButtonArray[i].className += (this.tabButtonArray[i].className == "" || this.tabButtonArray[i].className == null) ? "" : " ";
					this.tabButtonArray[i].className += "active";
				}
			}else{
				this.tabButtonArray[i].className = String(this.tabButtonArray[i].className).replace(regex,"");
			}

			display = (i==ind) ? "block" : "none";

			this.tabSet[i].displayObject.setStyle("display",display);

		}

	}

	this.removeTab = function(tab){

		var ind = tab.getAttribute("index");

		for(var i=0; i<this.tabSet.length;i++){

			if(i == ind){

				this.domElement.removeChild(this.tabButtonArray[i]);
				this.tabButtonArray.splice(i, 1);
				this.tabSet.splice(i, 1);

				if(this.selectedIndex == ind){

					if(this.tabButtonArray[i-1] != null){
						this.selectTab(this.tabButtonArray[i-1]);
					}else if(tabButtonArray[i] != null){
						this.selectTab(this.tabButtonArray[i]);
					}
				}
				break;
			}

		}

	}

	this.getSelectedTab = function(){

		return this.tabSet[this.selectedIndex];

	}

	this.TabSetObject();


}

TabSetObject.inherits(DisplayObject);// override getStoredValue method to query search socket

FormFieldElement.prototype.getStoredValue = function(){// method to return default value from search socket
	
	var val;

	if(RPWSearchSocket != null){
		val = RPWSearchSocket.getSearchSetting(this.fieldName);
		if(val != null){
			return val;
		}
	}
	
	return this.defaultValue;
			
}
	


function RPWLiveListObject(container){

	DisplayObject.call(this);
	
	this.setDOMElement(container);

	this.searchFormObj = null;// Search form object;
	this.propertyListObj = null;
	this.savedPropertyListObj = null;
	this.tabSetObj = null;
	this.resultsTab = null;
	this.shortlistTab = null;
	this.googleMapTab = null;
	this.googleMapObj = null;
	this.propertyDetailsObj = null;
	this.propertyDetailsTab = null;
	this.loadingGraphic = null;
	this.savedProperties = new Array();
	this.overlayObj = null;
	this.slideShowObj = null;
	this.selectedSearchTab = "results";
	this.serverTimeout = 20;
	
	this.inputPanel = null;
	this.viewsPanel = null;
	
	
	this.RPWLiveListObject = function(){
		
		// set default settings
		
		this.width = this.getWidth();
		
		this.setAttribute("thumbnailWidth",120);
		this.setAttribute("thumbnailHeight",90);
		
		this.setAttribute("mainImageHeight",320);
		this.setAttribute("mainImageWidth",this.width-240);
		
		this.setAttribute("RPWSearchFormObject.salesPriceBands","100000,200000,300000,400000,500000,650000,800000,1000000");
		this.setAttribute("RPWSearchFormObject.salesPriceBandLabels","100k,200k,300k,400k,500k,650k,800k,1m");
		this.setAttribute("RPWSearchFormObject.lettingsPriceBands","100,200,300,400,500,650,800,1000,1250,1500,2000");
		this.setAttribute("RPWSearchFormObject.lettingsPriceBandLabels","100pw,200pw,300pw,400pw,500pw,650pw,800pw,1000pw,1250pw,1500pw,2000pw");

		this.setAttribute("RPWSearchFormObject.showBeds",true);
		this.setAttribute("RPWSearchFormObject.maxBeds",7);
		
		this.setAttribute("RPWSearchFormObject.showKeyword",true);
		
		this.setAttribute("fitToBrowserWindow",true);
		
		this.domElement.className = "RPWLiveList";
		
	}
	
	this.init = function(){
		
		if(RPWSearchSocket == null){
			alert("Search socket not found. Please load file rpw-search-socket.js before rpw-live-list.js");
		}else{
			var thisObj = this;
			var onLoad = function(data){ thisObj.onPreferencesLoad(data)};
			
			RPWSearchSocket.loadUserPreferences(onLoad);
			
			if(this.getAttribute("newHomesOnly")){
				RPWSearchSocket.setSearchSetting("new_homes",1);
			}
		}
		
	}
	
	this.onPreferencesLoad = function(data){
		if(data != null && data.preferences != null){
			
			var j;
			for(var i in data.preferences){
				for(j in data.preferences[i]){}
				if(j.substr(0,18) == "RPWLiveListObject."){
					this.setAttribute(j.substr(18),data.preferences[i][j]);
				}
			}
		}
		
		
		this.displayContent();
		
	}
	
	this.savePreference = function(pref,val){
		
		if (RPWSearchSocket != null) {
			RPWSearchSocket.saveUserPreference("RPWLiveListObject." + pref, val);
		}
		
	}
	
	this.displayContent = function(){
	
		// set height
		
		this.width = this.getWidth();
		this.height = this.getHeight();
		
		// show loader
		this.inputPanel = this.addElement("div");
		this.inputPanel.className = "inputPanel";
		
		this.viewsPanel = this.addElement("div");
		this.viewsPanel.className = "viewsPanel";
		this.viewsPanel.style.position = "relative";
		
		this.showLoadingGraphic();
		
		// Set generic attributes
		
		this.applyDefaultStyles();
		
		var thisObj = this;
		
		if (RPWSearchSocket != null) {
		
			RPWSearchSocket.onSearchCompleteAction = function(data){
				thisObj.onSearchComplete(data)
			};
			
			RPWSearchSocket.setSearchSetting("search_description", this.getAttribute("RPWSearchSocketObject.searchDescription"));
			
			if(this.getAttribute("RPWSearchFormObject.searchType")){
				RPWSearchSocket.setSearchSetting("searchtype",this.getAttribute("RPWSearchFormObject.searchType"));
			}
			
			RPWSearchSocket.onSearchSettingsLoadAction = function(){
				thisObj.createElements();
			};
			
			RPWSearchSocket.loadSettings();
			
		}else{
			alert("RPW Search Socket not loaded");
		}
		
	}
	
	this.createElements = function(){
		
		this.createSearchForm();

		this.createPropertyList();
		
		this.createGoogleMap();
		
		this.createSavedPropertyList();
		
		this.createTabSet();
		
		// TITLE
	
		if(this.getAttribute("RPWSearchFormObject.searchFormTitle")){
			var titleElement = document.createElement("h3");
			titleElement.innerHTML = urlDecode(this.getAttribute("RPWSearchFormObject.searchFormTitle"));
			this.inputPanel.appendChild(titleElement);
		}

		this.searchFormObj.appendToElement(this.inputPanel);
		
		this.tabSetObj.appendToElement(this.viewsPanel);

		this.propertyListObj.appendToElement(this.viewsPanel);

		this.googleMapObj.appendToElement(this.viewsPanel);
		
		this.savedPropertyListObj.appendToElement(this.viewsPanel);

		this.loadSavedProperties();
			
		
		var thisObj = this;
		
		if(this.getAttribute("fitToBrowserWindow")){
			window.onresize = function(){thisObj.fitToWindow()};
		}
		
		if(getQueryVariable("view") == "map"){
			this.selectedSearchTab = "map";
			this.setAttribute("selectedSearchTab","map");
			this.tabSetObj.selectTab(this.googleMapTab);
		}
		
		this.fitToWindow();

		this.hideLoadingGraphic();
		
		if(RPWSearchSocket.resultTotal > 0){
			this.onSearchComplete({resultTotal: RPWSearchSocket.resultTotal});
		}else{
			RPWSearchSocket.doSearch();
		}
		
		
	}
	
	
	
	// SIZING METHODS
	
	
	this.fitToWindow = function(){
		
		if(this.getAttribute("fitToBrowserWindow")){
			
			var pageSizes = this.getPageSizeObject();
			
			this.setStyle("height",pageSizes.windowHeight+"px");
			
			this.resizeElements();

			document.location = "#"+this.domElement.id;
			
		}else{
			this.resizeElements();
		}
		
	}
	
	this.resizeElements = function(){
		
		this.resizePropertyList();
		this.resizeGoogleMap();
		this.resizeSavedPropertyList();
		this.resizePropertyDetails();
		
	}
	
	this.getViewPortSize = function(){
		
		var height = this.getHeight();
		var h = height - parseInt(this.getStyle("padding-top")) - parseInt(this.getStyle("padding-bottom")) - this.tabSetObj.getHeight();
		var w = this.getWidth(this.viewsPanel);

		if(document.all && !window.opera){
			h+= 24;
		}
		
		return {width:w,height:h};
		
	}
	
	this.resizePropertyList = function(){
		
		if (this.propertyListObj != null) {
			
			var apertureSize = this.getViewPortSize();
					
			var apertureHeight = apertureSize.height;
			var apertureWidth = apertureSize.width;
			
			this.propertyListObj.resizeTo(apertureWidth,apertureHeight);
		}
	
	}
	
	this.resizeGoogleMap = function(){
		
		if (this.googleMapObj != null) {
			
			var apertureSize = this.getViewPortSize();
					
			var apertureHeight = apertureSize.height;
			var apertureWidth = apertureSize.width;
			
			this.googleMapObj.resizeTo(apertureWidth,apertureHeight);
		}
	
	}
	
	this.resizeSavedPropertyList = function(){
		
		if (this.savedPropertyListObj != null) {
			
			var apertureSize = this.getViewPortSize();
					
			var apertureHeight = apertureSize.height;
			var apertureWidth = apertureSize.width;
			
			this.savedPropertyListObj.resizeTo(apertureWidth,apertureHeight);
		}
	
	}
	
	this.resizePropertyDetails = function(){
		
		if (this.propertyDetailsObj != null) {
			
			var apertureSize = this.getViewPortSize();
					
			var apertureHeight = apertureSize.height;
			var apertureWidth = apertureSize.width;
			
			this.propertyDetailsObj.resizeTo(apertureWidth,apertureHeight);
		}
	
	}
	
	
	
	
	
	
	
	this.createPropertyList = function(){
	
		if(this.domElement != null){
		
			// init object
			
			this.propertyListObj = new RPWPropertyListObject();
			this.propertyListObj.setParent(this);

		
			// position html element
			
			this.propertyListObj.displayContent();
			
		}
	
	
	}
	
	this.createSavedPropertyList = function(){
		
		if(this.domElement != null){
		
			// init object
			
			this.savedPropertyListObj = new RPWSavedPropertyListObject();
			this.savedPropertyListObj.setParent(this);

		
			// position html element
			
			this.savedPropertyListObj.displayContent();
			
		}
	
	
	}
	
	
	
	
	// Google Map methods
	
	this.createGoogleMap = function(){
	
		if(this.domElement != null){
			
		
			// init object
			
			this.googleMapObj = new RPWGoogleMapObject();
			this.googleMapObj.setParent(this);

			// position html element
			
			this.googleMapObj.displayContent();
			
		}
	
	
	}
	
	
	this.onMapTabSelect = function(){
		
		this.resizeGoogleMap();
		
		this.savePreference("selectedSearchTab","map");
		
		this.selectedSearchTab = "map";
		this.loadGMapResults();
	}
	
	this.loadGMapResults = function(){
		
		if(!this.googleMapObj.resultsDisplayed){
		
			this.googleMapObj.loadResults();
			
		}
		
	}
	
	this.createTabSet = function(){
	
		if(this.domElement != null){
		
			// init object
			
			this.tabSetObj = new TabSetObject();
			this.tabSetObj.setParent(this);
			
			var thisObj = this;
			var func = function(){thisObj.onResultsTabSelect()};

			
			this.resultsTab = this.tabSetObj.addTab("Search Results",this.propertyListObj,true,func);
			
			func = function(){thisObj.onMapTabSelect()};
			
			if(this.googleMapObj != null){
				this.googleMapTab = this.tabSetObj.addTab("Map",this.googleMapObj,false,func);
			}
			
			func = function(){thisObj.onShortlistTabSelect()};
			
			if (this.savedPropertyListObj != null) {
				this.shortlistTab = this.tabSetObj.addTab("Saved Properties", this.savedPropertyListObj, false, func);
			}
			
			this.tabSetObj.displayContent();
			
		
			// position html element
			
			if(this.getAttribute("selectedSearchTab") == "map"){
				this.tabSetObj.selectTab(this.googleMapTab);
				this.selectedSearchTab = "map";
			}
			
		}
	
	
	}
	
	this.addPropertyDetailsElement = function(){
		
		if(this.domElement != null){
			
			// init object
			
			this.propertyDetailsObj = new RPWPropertyDetailsViewerObject();
			this.propertyDetailsObj.setParent(this);

		
			
			
			this.propertyDetailsObj.displayContent();
			
			this.propertyDetailsObj.appendToElement(this.viewsPanel);
			
			this.propertyDetailsTab = this.tabSetObj.addTab("Property Details",this.propertyDetailsObj,false);

			
		}
	
		
	}
	
	this.createSearchForm = function(){
	
		if(this.domElement != null){
			
		
			// init object
			
			this.searchFormObj = new RPWSearchFormObject();
			this.searchFormObj.setParent(this);
			
			this.searchFormObj.loadAttributes();
		
			// position html element
			
			this.searchFormObj.setStyle("overflow","auto");
			
		}
	
	}
	
	this.applyDefaultStyles = function(){
	
		this.setStyle("position","relative");
	
	}
	
	
	
	
	
	// Search Handling
	
	this.onSearchComplete = function(data){
		
		this.updateResultTotal(data.resultTotal);
	
		if(this.googleMapObj != null){
			this.googleMapObj.resultsDisplayed = false;
		}
		
		this.propertyListObj.resultsDisplayed = false;
		
		if(this.selectedSearchTab == "map"){
			
			this.loadGMapResults();
			
			this.tabSetObj.selectTab(this.googleMapTab);
			
		}else{
			
			this.loadResultsList();
			
			this.tabSetObj.selectTab(this.resultsTab);
		}
		
		this.hideLoadingGraphic();
		
	}
	
	
	this.onResultsTabSelect = function(){
		
		this.resizePropertyList();
		
		this.selectedSearchTab = "results";
		
		this.savePreference("selectedSearchTab","results");
		
		this.loadResultsList();
		
	}
	
	
	this.loadResultsList = function(){
		
		if(!this.propertyListObj.resultsDisplayed){
		
			this.propertyListObj.loadSearchResults();
			
		}
		
	}
	
	this.updateResultTotal = function(total){
		
		this.resultsTab.innerHTML = "Search Results ("+total+")";
		
	}
	
	
	
	
	
	// Loading Graphic Methods
	
	this.showLoadingGraphic = function(){
		
		this.hideLoadingGraphic();
		
		this.loadingGraphic = new LoadingGraphicObject();
		
		this.loadingGraphic.setStyle("width",this.getWidth(this.viewsPanel)+"px");
		this.loadingGraphic.setStyle("height",this.getHeight(this.viewsPanel)+"px");
		this.loadingGraphic.setStyle("position","absolute");
		this.loadingGraphic.setStyle("top","0");
		this.loadingGraphic.setStyle("left","0");
		this.loadingGraphic.setStyle("z-index","1000");
		
		this.loadingGraphic.appendToElement(this.viewsPanel);
		
		this.loadingGraphic.displayContent();
		
		// set timeout
		var thisObj = this;
		
		this.serverTimeoutObj = setTimeout(function(){thisObj.onServerTimeout()},this.serverTimeout*1000);
	}
	
	this.hideLoadingGraphic = function(){
		
		if(this.loadingGraphic != null){
			this.loadingGraphic.removeFromElement(this.viewsPanel);
			this.loadingGraphic = null;
		}
		
		if(this.serverTimeoutObj != null){
			clearTimeout(this.serverTimeoutObj);
			this.serverTimeoutObj = null;
		}
		
	}
	
	this.onServerTimeout = function(){
		
		this.hideLoadingGraphic();
		alert("Sorry, the server has not responded. Please try again.");
		
	}
	
	
	
	// Saved Property Methods
	
	this.propertyIsSaved = function(dataObject){
		
		for(var i in this.savedProperties){
			
			if(this.savedProperties[i].db == dataObject.db && this.savedProperties[i].pcode == dataObject.pcode){
				return true;
			}
		}
		
		return false;
		
	}
	
	this.saveProperty = function(dataObject){
		
		if(this.propertyIsSaved(dataObject)){
			return;
		}
		
		this.addToShortlist(dataObject);
		
		// save to session
		
		if(RPWSearchSocket != null){
			RPWSearchSocket.saveShortlistToSession("shortlist",this.savedProperties);
		}
		
	}
	
	this.addToShortlist = function(dataObject){
		
		// add to internal array
		
		this.savedProperties.push(dataObject);
		
		
		// add to list
		
		if(this.savedPropertyListObj != null){
			
			this.savedPropertyListObj.addItem(dataObject);
			
			this.updateShortlistTotal();
			
		}
		
		
		// amend results list & map
		
		if(this.propertyListObj != null){
			
			this.propertyListObj.markItemAsSaved(dataObject,true);
			
		}
		
		if(this.googleMapObj != null){
			
			this.googleMapObj.markItemAsSaved(dataObject,true);
			
		}
		
		if(this.propertyDetailsObj != null){
			
			this.propertyDetailsObj.markItemAsSaved(dataObject,true);
			
		}

		if(this.slideShowObj != null){
			
			this.slideShowObj.markAsSaved(dataObject,true);
			
		}
		
		
	}
	
	this.removeSavedProperty = function(dataObject){
		
		for(var i in this.savedProperties){
			
			if(this.savedProperties[i].db == dataObject.db && this.savedProperties[i].pcode == dataObject.pcode){
				this.savedProperties.splice(i,1);
			}
		}
		
		if(this.savedPropertyListObj != null){
			
			this.savedPropertyListObj.removeItem(dataObject);
			
			this.updateShortlistTotal();
			
		}
		
		if(this.propertyListObj != null){
			
			this.propertyListObj.markItemAsSaved(dataObject,false);
			
		}
		
		if(this.googleMapObj != null){
			
			this.googleMapObj.markItemAsSaved(dataObject,false);
			
		}

		if(this.propertyDetailsObj != null){
			
			this.propertyDetailsObj.markItemAsSaved(dataObject,false);
			
		}

		if(this.slideShowObj != null){
			
			this.slideShowObj.markAsSaved(dataObject,false);
			
		}
		
		if(RPWSearchSocket != null){
			RPWSearchSocket.saveShortlistToSession("shortlist",this.savedProperties);
		}
		
	}
	
	this.updateShortlistTotal = function(){
		
		if(this.savedPropertyListObj != null){
			
			this.shortlistTab.innerHTML = "Saved Properties ("+this.savedPropertyListObj.getTotal()+")";
			
		}
	}
	
	this.loadSavedProperties = function(){
		
		if(RPWSearchSocket != null){
			
			var thisObj = this;
			var func = function(dataObj){thisObj.onShortlistLoad(dataObj);};
			
			RPWSearchSocket.loadShortlist("shortlist", func);
			
		}
	}
	
	this.onShortlistLoad = function(dataObj){
		
		if(dataObj.properties != null){
			
			for(var i in dataObj.properties){
				
				this.addToShortlist(dataObj.properties[i]);
				
			}
			
		}
	}
	
	this.onShortlistTabSelect = function(){
		
		this.resizeSavedPropertyList();
		
	}
	
	
	// Slideshow methods
	
	this.showPropertySlideShow = function(dataObject,type){
		
		this.removePropertySlideShow();
		
		var thisObj = this;
		var removeFunc = function(e){ thisObj.closeSlideShow(); };
		
		this.overlayObj = this.addOverlay(removeFunc);
		
		this.overlayObj.setStyle("z-index",100);
		
		this.slideShowObj = new RPWPropertySlideShowObject(dataObject);
		
		this.slideShowObj.setParent(this);
		
		removeFunc = function(e){ thisObj.closeSlideShow(); };
		
		this.slideShowObj.onRemoveFunction = removeFunc;

		this.slideShowObj.setStyle("z-index",200);
		
		var bodyObj = document.getElementsByTagName("body").item(0);
		
		this.slideShowObj.appendToElement(bodyObj);
		
		this.slideShowObj.displayContent(type);
		
		return this.slideShowObj;
		
		
	}
	
	this.closeSlideShow = function(){
		
		if(this.overlayObj != null){
			this.overlayObj.remove();
		}
		
		this.removePropertySlideShow();
	}
	
	this.removePropertySlideShow = function(){
		
		if(this.slideShowObj != null){
			
			var bodyObj = document.getElementsByTagName("body").item(0);
			
			this.slideShowObj.removeFromElement(bodyObj);
			this.slideShowObj = null;
			
		}
		
	}
	
	
	
	// MAP METHODS
	
	this.showPropertyOnMap = function(dataObject){
		
		if(this.googleMapObj != null){
			
			
			this.resizeGoogleMap();
			
			this.googleMapObj.showProperty(dataObject);
			this.tabSetObj.selectTab(this.googleMapTab);
			
			
		}
		
	}
		
	
	// Property details methods
	
	this.showPropertyDetails = function(dataObject){
		
		if(this.propertyDetailsObj == null){
			this.addPropertyDetailsElement();
		}
		
		
		this.propertyDetailsObj.showPropertyDetails(dataObject)
		this.resizePropertyDetails();

		this.tabSetObj.selectTab(this.propertyDetailsTab);
		
	}
	
	this.removePropertyDetails = function(){
		
		if(this.propertyDetailsObj != null){
			
			this.propertyDetailsObj.removeFromElement(this.domElement);
			this.tabSetObj.removeTab(this.propertyDetailsTab);
			
			this.propertyDetailsTab = null;
			this.propertyDetailsObj = null;
		}
		
		
		
	}
	

	// Overlay methods
	
	this.addOverlay = function(onRemove){
		
		this.overlayObj = new OverlayObject();
		this.overlayObj.setParent(this);
		this.overlayObj.displayContent();
		this.overlayObj.onRemoveFunction = onRemove;
		return this.overlayObj;
	}
	

	
	
	
	// init object
	
	if(this.domElement == null){
		document.write("Please supply a valid container for the object");
	}else{
		this.RPWLiveListObject();
	}
	
	
}

RPWLiveListObject.inherits(DisplayObject);
function RPWSearchFormObject(){

	FormObject.call(this,"rpwSearchForm");

	this.domElement.onsubmit = function(){ return false; };

	this.typeSelectElement = null;
	this.minPriceElement = null;
	this.maxPriceElement = null;
	this.officeSelectElement = null;
	this.newInstructionSelector = null;
	this.keywordElement = null;

	this.offices = new Object();
	this.offices.sales = new Array();
	this.offices.lettings = new Array();

	this.RPWSearchFormObject = function(){



	}


	this.loadAttributes = function(){

		if(RPWSearchSocket != null){
			var thisObj = this;
			RPWSearchSocket.onSearchFormAttributesLoadAction = function(dataObj){ thisObj.displayContent(dataObj); };

			// build query string

			var qString = "";

			if(this.getAttribute("RPWSearchFormObject.dcode")){
				qString += "&dcode="+this.getAttribute("RPWSearchFormObject.dcode");
			}

			if(this.getAttribute("RPWSearchFormObject.propertyTypeDepFields")){
				qString += "&propertyTypeDepFields="+this.getAttribute("RPWSearchFormObject.propertyTypeDepFields");
			}

			if(this.getAttribute("RPWSearchFormObject.locationDepGroup")){
				qString += "&locationDepGroup="+this.getAttribute("RPWSearchFormObject.locationDepGroup");
			}

			if(this.getAttribute("RPWSearchFormObject.propertyLocationDepFields")){
				qString += "&propertyLocationDepFields="+this.getAttribute("RPWSearchFormObject.propertyLocationDepFields");
			}

			if(this.getAttribute("RPWSearchFormObject.gardenDepGroup")){
				qString += "&gardenDepGroup="+this.getAttribute("RPWSearchFormObject.gardenDepGroup");
			}

			if(this.getAttribute("RPWSearchFormObject.propertyGardenDepFields")){
				qString += "&propertyGardenDepFields="+this.getAttribute("RPWSearchFormObject.propertyGardenDepFields");
			}

			RPWSearchSocket.loadSearchFormAttributes(qString);
		}
	}


	this.displayContent = function(dataObj){

		this.clearContents();

		var parentObj = this.getParent();

		var thisObj = this;

		var elementOnChange = function(element,formFieldObj){
			thisObj.onSearchSettingChange(element,formFieldObj);
		};


		// TYPE

		var searchType = "sales";

		if (this.getAttribute("RPWSearchFormObject.searchType") == "both") {

			savedValue = (RPWSearchSocket != null) ? RPWSearchSocket.getSearchSetting("searchtype") : null;

			this.typeSelectElement = this.addSelectField("searchtype", "Search", savedValue, "sales,lettings","Sales,Lettings");
			var onTypeChange

			if (RPWSearchSocket != null) {
				onTypeChange = function(element){
					thisObj.setPriceDropDowns();
					thisObj.setOfficeDropDown();
					thisObj.onSearchSettingChange(element);
				}
			}else{
				onTypeChange = function(element){
					thisObj.setPriceDropDowns();
					thisObj.setOfficeDropDown();
				}
			}

			this.typeSelectElement.setOnChangeListener(onTypeChange);

			if(savedValue != null){
				searchType = savedValue;
			}

		}else if(this.getAttribute("RPWSearchFormObject.searchType") == "lettings"){
			if (RPWSearchSocket != null) {
				RPWSearchSocket.setSearchSetting("searchtype", "lettings");
			}
			searchType = "lettings";
		}

		// PRICES

		var savedValue = (RPWSearchSocket != null) ? RPWSearchSocket.getSearchSetting("min_price") : null;
		this.minPriceElement = this.addSelectField("min_price","Min. price",savedValue,"0,"+this.getAttribute("RPWSearchFormObject."+searchType+"PriceBands"),"0,"+this.getAttribute("RPWSearchFormObject."+searchType+"PriceBandLabels"));
		if(RPWSearchSocket != null){
			this.minPriceElement.setOnChangeListener(elementOnChange);
		}

		savedValue = (RPWSearchSocket != null && RPWSearchSocket.getSearchSetting("max_price") != null) ? RPWSearchSocket.getSearchSetting("max_price") : "~";
		this.maxPriceElement = this.addSelectField("max_price","Max. price",savedValue,this.getAttribute("RPWSearchFormObject."+searchType+"PriceBands")+",~",this.getAttribute("RPWSearchFormObject."+searchType+"PriceBandLabels")+",No limit");
		if(RPWSearchSocket != null){
			this.maxPriceElement.setOnChangeListener(elementOnChange);
		}

		// BEDROOMS

		if(this.getAttribute("RPWSearchFormObject.showBeds")){
			savedValue = (RPWSearchSocket != null) ? RPWSearchSocket.getSearchSetting("num_beds") : null;
			var bedStr = "";
			var maxBeds = (this.getAttribute("RPWSearchFormObject.maxBeds")) ? this.getAttribute("RPWSearchFormObject.maxBeds") : 7;
			for(var i=0;i<=maxBeds;i++){
				bedStr += (bedStr == "") ? "" : ",";
				bedStr += i;
			}

			element = this.addSelectField("num_beds","Bedrooms",savedValue,bedStr);
			if(RPWSearchSocket != null){
				element.setOnChangeListener(elementOnChange);
			}

		}

		// FURNISH

		if(this.getAttribute("RPWSearchFormObject.showFurnishOptions")){
			savedValue = (RPWSearchSocket != null) ? RPWSearchSocket.getSearchSetting("furnish_state") : null;

			element = this.addMultiSelectField("furnish_state","Furnish",savedValue,"F,P,U","Furnished,Part-furnished,Unfurnished");
			if(RPWSearchSocket != null){
				element.setOnChangeListener(elementOnChange);
			}

		}


		// OFFICES
		if(this.getAttribute("RPWSearchFormObject.showOffices") && dataObj.offices){
			savedValue = (RPWSearchSocket != null) ? RPWSearchSocket.getSearchSetting("ocode") : null;

			var values = "";
			var labels = "All";
			var officeType = "sales"

			for(var i in dataObj.offices){

				officeType = (dataObj.offices[i].type == "lettings") ? "lettings" : "sales";
				this.offices[officeType].push({value:dataObj.offices[i].rps + "-" + dataObj.offices[i].ocode,label:dataObj.offices[i].name});

				if (officeType == searchType) {
					values += "," + dataObj.offices[i].rps + "-" + dataObj.offices[i].ocode;
					labels += "," + dataObj.offices[i].name;
				}
			}

			this.officeSelectElement = this.addSelectField("ocode","Office",savedValue,values,labels);
			if(RPWSearchSocket != null){
				this.officeSelectElement.setOnChangeListener(elementOnChange);
			}
		}

		// AREAS

		if(this.getAttribute("RPWSearchFormObject.searchAreas")){

			var areaArray = this.getAttribute("RPWSearchFormObject.searchAreas");

			var values = new Array();
			var labels = new Array();

			for (var i in areaArray) {
				values.push(areaArray[i].value);
				labels.push(areaArray[i].label);
			}

			if (this.getAttribute("RPWSearchFormObject.searchAreaInput") == "flyout") {

				this.areaFormLine = this.addLine("Areas");
				this.areaSummary = this.areaFormLine.addElement("span");
				this.areaSummary.className = "areaSummary";
				this.areaSummary.style.display = "none";
				this.areaSummaryLink = document.createElement("a");
				this.areaSummaryLink.setAttribute("href","javascript:void(0);");
				this.areaSummaryLink.onclick = function(){thisObj.showAreaFlyout()};
				this.areaSummary.appendChild(this.areaSummaryLink);

				this.areaFlyoutButton = this.areaFormLine.addElement("a");
				this.areaFlyoutButton.setAttribute("href","javascript:void(0);");
				this.areaFlyoutButton.innerHTML = "<span>Select</span>";
				this.areaFlyoutButton.className = "areaFlyoutButton";

				this.areaFlyoutButton.onclick = function(){thisObj.showAreaFlyout()};

				this.areaFlyout = this.areaFormLine.addElement("div");
				this.areaFlyout.style.display = "none";
				this.areaFlyout.style.position = "absolute";
				this.areaFlyout.className = "areaFlyout";

				savedValue = null;

				var searchSettings = RPWSearchSocket.getSearchSettings();

				if(searchSettings != null){
					savedValue = new Array();
					for(var j in searchSettings){
						if(j.substr(0,8) == "area_str"){
							savedValue.push(searchSettings[j]);
						}
					}
					savedValue = (savedValue.length > 0) ? savedValue.join(",") : null;
				}

				element = new MultiSelectElement("area_str_","Area",savedValue,values,labels,"ordinal");
				element.displayContent();
				element.appendToElement(this.areaFlyout);
				element.setParent(this);

				this.areaSelectElement = element;

				var flyoutCloseButton = document.createElement("a");
				flyoutCloseButton.setAttribute("href","javascript:void(0);");
				flyoutCloseButton.setAttribute("title","Close");
				flyoutCloseButton.className = "closeButton";
				flyoutCloseButton.innerHTML = "<span>Close</span>";

				flyoutCloseButton.onclick = function(){thisObj.hideAreaFlyout();}

				this.areaFlyout.appendChild(flyoutCloseButton);

				this.inputArray.push(element);

				this.updateAreaSummary();

			}else if(this.getAttribute("RPWSearchFormObject.searchAreaInput") == "checkboxes"){

				savedValue = null;

				var searchSettings = RPWSearchSocket.getSearchSettings();

				if(searchSettings != null){
					savedValue = new Array();
					for(var j in searchSettings){
						if(j.substr(0,8) == "area_str"){
							savedValue.push(searchSettings[j]);
						}
					}
					savedValue = (savedValue.length > 0) ? savedValue.join(",") : null;
				}

				element = this.addMultiSelectField("area_str_","Areas",savedValue,values,labels,"ordinal");

				this.areaSelectElement = element;


				if(RPWSearchSocket != null){
					element.setOnChangeListener(elementOnChange);
				}
			}else{

				savedValue = (RPWSearchSocket != null) ? RPWSearchSocket.getSearchSetting("area_str_0") : null;


				if (this.getAttribute("RPWSearchFormObject.searchAreaInput") == "multi-select") {
					var selectSize = (this.getAttribute("RPWSearchFormObject.searchAreaSize")) ? this.getAttribute("RPWSearchFormObject.searchAreaSize") : 8;
					element = this.addMultipleSelectField("area_str_0", "Area", savedValue, values, labels, selectSize,"area");
				}else{
					values.unshift("");
					labels.unshift("All areas");
					element = this.addSelectField("area_str_0", "Area", savedValue, values, labels);
				}

				this.areaSelectElement = element;

				if(RPWSearchSocket != null){
					element.setOnChangeListener(elementOnChange);
				}
			}

		}

		// KEYWORD

		if(this.getAttribute("RPWSearchFormObject.showKeyword")){
			var webAreas;
			if(webAreas = this.getAttribute("RPWSearchFormObject.webAreas")){

				savedValue = (RPWSearchSocket != null) ? RPWSearchSocket.getSearchSetting("webarea") : null;
				var label = (this.getAttribute("RPWSearchFormObject.keywordLabel")) ? this.getAttribute("RPWSearchFormObject.keywordLabel") : "Area";

				this.webareaElement = this.addTextField("webarea",label,savedValue);

				/*if(RPWSearchSocket != null){
					this.keywordElement.setOnChangeListener(elementOnChange);
				}*/

				var keywordInput = this.webareaElement.inputObject;

				$(keywordInput).autocomplete(webAreas);
				$(keywordInput).result(function(event, data, formatted) {
			 		var regex = / ?\([^\)]+\)/;
					$(keywordInput).val(String(data).replace(regex,''));
					thisObj.onSearchSettingChange(keywordInput);
				});

			}else{
				savedValue = (RPWSearchSocket != null) ? RPWSearchSocket.getSearchSetting("keywords") : null;
				var label = (this.getAttribute("RPWSearchFormObject.keywordLabel")) ? this.getAttribute("RPWSearchFormObject.keywordLabel") : ((this.getAttribute("RPWSearchSocketObject.searchDescription")) ? "Keywords" : "Area");
				this.keywordElement = this.addTextField("keywords",label,savedValue);
				if(RPWSearchSocket != null){
					this.keywordElement.setOnChangeListener(elementOnChange);
				}
			}
		}

		// DEPS

		var label = "";

		// PROPERTY TYPE
		if(this.getAttribute("RPWSearchFormObject.showPropertyTypes") && dataObj.propertyTypes){
			label = (this.getAttribute("RPWSearchFormObject.propertyTypeLabel")) ? this.getAttribute("RPWSearchFormObject.propertyTypeLabel") : "Type";
			this.addDepGroup(dataObj.propertyTypes,label);
		}

		// PROPERTY LOCATION
		if(this.getAttribute("RPWSearchFormObject.showPropertyLocations") && dataObj.locations){
			label = (this.getAttribute("RPWSearchFormObject.locationLabel")) ? this.getAttribute("RPWSearchFormObject.locationLabel") : "Location";
			this.addDepGroup(dataObj.locations,label);
		}

		// LAND OPTIONS
		if(this.getAttribute("RPWSearchFormObject.showPropertyLandOptions") && dataObj.landOptions){
			label = (this.getAttribute("RPWSearchFormObject.gardenLabel")) ? this.getAttribute("RPWSearchFormObject.gardenLabel") : "Land";
			this.addDepGroup(dataObj.landOptions,label);
		}

		this.addNewInstructionOptions();

		this.addRecentlyReducedOption();

		this.domElement.className = "RPWSearchForm";

		var thisObj = this;

		for(var i in this.fieldElements){

			if(RPWSearchSocket != null){

				this.fieldElements[i].setOnChangeListener(thisObj.onSearchSettingChange);

			}

			this.fieldElements[i].displayContent();

			this.domElement.appendChild(this.fieldElements[i].getDOMElement());

		}

		/*this.formSubmitObject = this.getFormSubmitElement();

		this.domElement.appendChild(this.formSubmitObject);*/

	}

	this.onSearchSettingChange = function(element,formFieldObj){

		if (element.name == "furnish_state[]") {
			RPWSearchSocket.setSearchSetting("furnish_state", formFieldObj.getValue());
		} else {
			RPWSearchSocket.inputSearchSetting(element);
		}

		if(this.getAttribute("RPWSearchFormObject.areaFieldsExclusive") && (element.name == "ocode" || element.name == "keywords" || element.name.substr(0,8) == "area_str" || element.name == "webarea")){
			this.resetAreaFields(element.name);
		}

		var parentObj = this.getParent();

		parentObj.showLoadingGraphic();
		RPWSearchSocket.doSearch();
	}


	this.resetAreaFields = function(type){
		if(type != "ocode"){
			if (this.officeSelectElement != null) {
				this.officeSelectElement.reset();
			}
			RPWSearchSocket.setSearchSetting("ocode",null);
		}
		if(type != "keywords"){
			if (this.keywordElement != null) {
				this.keywordElement.reset();
			}
			RPWSearchSocket.setSearchSetting("keywords",null);
		}
		if(type != "webarea"){
			if (this.webareaElement != null) {
				this.webareaElement.reset();
			}
			RPWSearchSocket.setSearchSetting("webarea",null);
		}
		if(type.substr(0,8) != "area_str" && this.areaSelectElement != null){
			this.areaSelectElement.reset();
			this.updateAreaSummary();
			RPWSearchSocket.clearAreas();
		}

		RPWSearchSocket.setSearchSetting("north",null);
		RPWSearchSocket.setSearchSetting("east",null);
		RPWSearchSocket.setSearchSetting("south",null);
		RPWSearchSocket.setSearchSetting("west",null);
	}

	this.clearContents = function(){

		if(this.formObject != null){

			for(var i in this.fieldElements){

				this.formObject.removeChild(this.fieldElements[i].getDOMElement());

			}

			this.formObject.removeChild(this.formSubmitObject);

			this.formSubmitObject = null;

			this.domElement.removeChild(this.formObject);

			this.formObject = null;

		}

	}

	this.setPriceDropDowns = function(){

		if(this.typeSelectElement != null){
			var searchType = this.typeSelectElement.getValue();
			this.minPriceElement.setOptions("0,"+this.getAttribute("RPWSearchFormObject."+searchType+"PriceBands"),"0,"+this.getAttribute("RPWSearchFormObject."+searchType+"PriceBandLabels"));
			this.minPriceElement.displayContent();
			this.maxPriceElement.setOptions(this.getAttribute("RPWSearchFormObject."+searchType+"PriceBands")+",~",this.getAttribute("RPWSearchFormObject."+searchType+"PriceBandLabels")+",No limit");
			this.maxPriceElement.displayContent();
		}

	}

	this.setOfficeDropDown = function(){

		if(this.typeSelectElement != null && this.officeSelectElement != null){
			var searchType = this.typeSelectElement.getValue();
			if(this.offices[searchType].length > 0){
				var values = new Array("");
				var labels = new Array("All");
				for(var i in this.offices[searchType]){
					values.push(this.offices[searchType][i].value);
					labels.push(this.offices[searchType][i].label);
				}
			}
			this.officeSelectElement.setOptions(values,labels);
			this.officeSelectElement.displayContent();
			if(RPWSearchSocket != null){
				RPWSearchSocket.setSearchSetting("ocode",null);
			}
		}

	}

	this.showAreaFlyout = function(){

		this.areaFlyout.style.display = "block";
	}

	this.hideAreaFlyout = function(){

		this.updateAreaSummary();

		this.areaFlyout.style.display = "none";

		var parentObj = this.getParent();

		var value;

		if (RPWSearchSocket != null) {

			for(var i in this.areaSelectElement.checkboxArr){

				value = (this.areaSelectElement.checkboxArr[i].checked) ? this.areaSelectElement.checkboxArr[i].value : null;

				RPWSearchSocket.setSearchSetting(this.areaSelectElement.checkboxArr[i].name,value);
			}

			if(this.getAttribute("RPWSearchFormObject.areaFieldsExclusive")){
				this.resetAreaFields("area_str");
			}

			parentObj.showLoadingGraphic();

			RPWSearchSocket.doSearch();
		}
	}


	this.updateAreaSummary = function(){

		if (this.getAttribute("RPWSearchFormObject.searchAreas") && this.areaSummaryLink != null) {

			var areaArray = this.getAttribute("RPWSearchFormObject.searchAreas");

			var summaryStr = "";

			var searchSettings = this.areaSelectElement.getValue();

			var pattern;

			if (searchSettings != null) {

				savedValue = new Array();

				for (var i in areaArray) {
					pattern = new RegExp("(^|,)"+areaArray[i].value+"(,|$)");
					if (pattern.test(searchSettings)) {
						summaryStr += (summaryStr == "") ? "" : ", ";
						summaryStr += areaArray[i].label;
					}
				}
			}

			this.areaSummaryLink.innerHTML = summaryStr;

			if(summaryStr == ""){
				this.areaSummary.style.display = "none";
				this.areaFlyoutButton.style.display = "inline-block";
			}else{
				this.areaSummary.style.display = "inline";
				this.areaFlyoutButton.style.display = "none";
			}

		}


	}

	this.getFormSubmitElement = function(){

		var element = document.createElement("p");
		element.className = "formSubmit";

		var input = document.createElement("input");
		input.setAttribute("type","button");
		input.setAttribute("value","Show Properties");

		var thisObj = this;

		if(RPWSearchSocket != null){
			input.onclick = function(){thisObj.doSearch()};
		}


		element.appendChild(input);

		return element;

	}

	this.addDepGroup = function(dataObject,fieldLabel){

		var fieldName = dataObject[0].name.substr(0,5)+"_";

		var savedValue = "";

		if(RPWSearchSocket != null){

			var thisObj = this;
			var elementOnChange = function(element){
				thisObj.onSearchSettingChange(element);
			};

			settings = RPWSearchSocket.getSearchSettings();
			for(i in settings){
				if(i.substr(0,5) == fieldName.substr(0,5)){
					savedValue += (savedValue == "") ? "" : ",";
					savedValue += settings[i];
				}
			}
		}

		var values = "";
		var labels = "";

		for(var i in dataObject){
			values += (values == "") ? "" : ",";
			labels += (labels == "") ? "" : ",";
			values += dataObject[i].value;
			labels += dataObject[i].label;
		}
		var element = this.addMultiSelectField(fieldName,fieldLabel,savedValue,values,labels,"ordinal");

		if(RPWSearchSocket != null){
			element.setOnChangeListener(elementOnChange);
		}

		return element;
	}

	this.addRecentlyReducedOption = function(){
		if (this.getAttribute("RPWSearchFormObject.showRecentlyReduced")) {

			var savedValue = false;
			if (RPWSearchSocket != null) {
				savedValue = (RPWSearchSocket.getSearchSetting("reducedsince") == this.getAttribute("RPWSearchFormObject.recentlyReducedPeriod")+" ago");
			}

			var line = this.addLine(null,"");

			var element = new CheckBoxElement("reducedsince",null,savedValue,this.getAttribute("RPWSearchFormObject.recentlyReducedPeriod")+" ago");
			element.displayContent();
			element.appendToElement(line.domElement);
			element.setParent(this);

			line.addText(" Recent price reductions");

			var thisObj = this;
			var parentObj = this.getParent();

			var elementOnChange = function(element){
				thisObj.onSearchSettingChange(element);
				parentObj.showLoadingGraphic();
			};

			element.setOnChangeListener(elementOnChange);

			return element;

		}
	}

	this.addNewInstructionOptions = function(){

		// NEW INSTRUCTIONS
		if (this.getAttribute("RPWSearchFormObject.newInstructionPeriods")) {
			var periods = String(this.getAttribute("RPWSearchFormObject.newInstructionPeriods")).split(",");
			var labels = new Array();
			var values = new Array();
			var savedValue = "";
			if (RPWSearchSocket != null) {
				savedValue = RPWSearchSocket.getSearchSetting("timestamp");
			}

			var value;
			var regex = /^\D/;

			for(var i in periods){

				value = periods[i]+" ago";

				// add 1 to period if not there
				if(regex.test(value)){
					value = "1 "+value;
				}

				values.push(value);
				labels.push("Last "+periods[i]);
			}

			var label = (this.getAttribute("RPWSearchFormObject.newInstructionLabel")) ? this.getAttribute("RPWSearchFormObject.newInstructionLabel") : "Added";


			this.newInstructionSelector = this.addMultiSelectField("timestamp",label,savedValue,values,labels,"ordinal");

			var thisObj = this;
			var elementOnChange = function(element){ thisObj.selectNewInstructionPeriod(element);};
			this.newInstructionSelector.setOnChangeListener(elementOnChange);
		}

	}

	this.selectNewInstructionPeriod = function(element){

		if(this.newInstructionSelector != null){

			var checkBoxArray = this.newInstructionSelector.checkboxArr;

			for(var i in checkBoxArray){
				if(checkBoxArray[i].value == element.value && element.checked){
					checkBoxArray[i].checked = true;
				}else{
					checkBoxArray[i].checked = false;
				}
			}

			if (RPWSearchSocket != null) {
				var value = (element.checked) ? element.value : null;
				RPWSearchSocket.setSearchSetting("timestamp",value);
				var parentObj = this.getParent();
				parentObj.showLoadingGraphic();
				RPWSearchSocket.doSearch();
			}

		}

	}


	this.doSearch = function(){

		if(RPWSearchSocket != null){

			this.parentObj.showLoadingGraphic();
			RPWSearchSocket.doSearch();

		}
	}

	this.RPWSearchFormObject();

}

RPWSearchFormObject.inherits(FormObject);
function RPWPropertyListObject(){

	DisplayObject.call(this);

	// sub-elements
	this.statusObject = null; // div to display status
	this.listContainer = null;
	this.listObject = null; // UL list object to display results
	this.navigationElementTop = null;
	this.navigationElementBottom = null;
	this.totalDisplay = null;// div to display totals
	this.noResultObject = null;// div to display no results message

	this.orderSelector = null;

	// settings

	this.offset = 0;// page offset.
	this.displayCount = 10;// properties per page
	this.recordTotal = 0;

	this.resultsDisplayed = false;

	this.itemArray = new Array();

	//

	this.overlay = null;
	this.mortgageCalculator = null;

	this.activeProperty = null;




	this.RPWPropertyListObject = function(){

		this.createDOMElement("div","RPWPropertyList");

	}

	// DOM methods

	this.displayContent = function(){

		this.addStatusBar();

		// add list container

		this.listContainer = this.addDisplayObject("div");

		this.listContainer.setStyle("position","relative");

		if (!this.getAttribute("RPWPropertyListObject.usePageSets")) {
			this.listContainer.setStyle("overflow", "auto");
			this.addOnScroll();
		}

		this.listObject = this.listContainer.addElement("ul");
		this.listObject.className = "itemList";

		if (this.getAttribute("RPWPropertyListObject.usePageSets")) {
			this.navigationElementBottom = this.addDisplayObject("p");
			this.navigationElementBottom.setClass("navigation");
		}



		this.applyDefaultStyles();

	}


	this.resizeTo = function(w,h){
		//this.setStyle("width",w+"px");
		h -= parseInt(this.getStyle("padding-top"));
		h -= parseInt(this.getStyle("padding-bottom"));

		this.setStyle("height",h+"px");

		if (this.statusObject != null) {

			h -= this.statusObject.getHeight();

		}

		this.listContainer.setStyle("height",h+"px");
	}

	this.addOnScroll = function(){

		if(this.listContainer != null){

			var thisObj = this;
			this.listContainer.domElement.onscroll = function(){ thisObj.onListScroll(this); };


		}
	}


	this.addStatusBar = function(){
		// add status bar

		this.statusObject = this.addDisplayObject("div");
		if (this.getAttribute("RPWPropertyListObject.usePageSets")) {
			this.statusObject.setClass("statusBar extended");
		} else {
			this.statusObject.setClass("statusBar");
		}

		var controlPanel = this.statusObject.addElement("div");
		controlPanel.className = "control";

		if(this.getAttribute("RPWPropertyListObject.showMortgageCalculator")){

			var mortgageCalculatorLink = this.getMortgageCalculatorLink();
			if(mortgageCalculatorLink != null){
				mortgageCalculatorLink.appendToElement(controlPanel);
			}
		}


		var orderSelector = this.getOrderSelectorElement();

		if(orderSelector != null){
			orderSelector.appendToElement(controlPanel);
		}


		// add total display/navigation

		this.totalDisplay = this.statusObject.addElement("p");
		this.totalDisplay.className = "listStatus";

		if (this.getAttribute("RPWPropertyListObject.usePageSets")) {
			this.navigationElementTop = this.statusObject.addDisplayObject("p");
			this.navigationElementTop.setClass("navigation");
		}

	}

	this.getOrderSelectorElement = function(){

		var element = this.addDisplayObject("span");
		element.setClass("resultOrderSelector");

		element.addText("Order by ");

		var orderBy, orderDesc, option;

		if(RPWSearchSocket != null){
			orderBy = RPWSearchSocket.getSearchSetting("order_by");
			orderDesc = RPWSearchSocket.getSearchSetting("order_desc");
		}

		this.orderSelector = document.createElement("select");

		option = document.createElement("option");
		option.value = "pprice";
		option.text = "Price: low to high";

		try {
			this.orderSelector.add(option, null); // standards compliant; doesn't work in IE
		}
		catch(ex) {
			this.orderSelector.add(option); // IE only
		}

		option = document.createElement("option");
		option.value = "pprice desc";
		option.text = "Price: high to low";

		if((orderBy == null || orderBy == "pprice") && orderDesc == true){
			option.setAttribute("selected","selected");
		}

		try {
			this.orderSelector.add(option, null); // standards compliant; doesn't work in IE
		}
		catch(ex) {
			this.orderSelector.add(option); // IE only
		}

		var thisObj = this;

		this.orderSelector.onchange = function(){ thisObj.changeOrder(this);};

		element.appendChild(this.orderSelector);

		return element;
	}

	this.getMortgageCalculatorLink = function(){

		var element = this.addDisplayObject("span");
		element.setClass("mortgageCalculatorLink");

		var a = element.addElement("a");
		a.setAttribute("href","javascript:void(0);");
		a.innerHTML = "Mortgage Calculator";

		var thisObj = this;
		a.onclick = function(){ thisObj.showMortgageCalculator(); };

		return element;

	}

	this.showMortgageCalculator = function(price){

		var parentObj = this.getParent();

		if(price == null && this.activeProperty != null){
			price = this.activeProperty.getPrice();
		}

		var thisObj = this;
		var removeFunc = function(){ thisObj.removeMortgageCalculator(); };

		this.overlay = parentObj.addOverlay(removeFunc);
		this.overlay.setStyle("z-index",1000);

		this.mortgageCalculator = new RPWMortgageCalculatorObject();

		this.mortgageCalculator.setParent(this);

		this.mortgageCalculator.isStandAlone = !this.getAttribute("RPWPropertyListObject.showMortgageRepayments");
		this.mortgageCalculator.showDepositField = !this.getAttribute("RPWMortgageCalculatorObject.hideDepositField");

		if(price != null){
			this.mortgageCalculator.setValue(price);
		}

		if(this.getAttribute("RPWMortgageCalculatorObject.introStr")){
			this.mortgageCalculator.setIntro(this.getAttribute("RPWMortgageCalculatorObject.introStr"));
		}
		if(this.getAttribute("RPWMortgageCalculatorObject.caveatStr")){
			this.mortgageCalculator.setCaveat(this.getAttribute("RPWMortgageCalculatorObject.caveatStr"));
		}

		this.mortgageCalculator.onRemoveFunction = removeFunc;

		this.mortgageCalculator.setStyle("z-index",1020);

		var bodyObj = document.getElementsByTagName("body").item(0);

		this.mortgageCalculator.appendToElement(bodyObj);

		this.mortgageCalculator.displayContent();

		return this.mortgageCalculator;


	}

	this.removeMortgageCalculator = function(){

		if(this.overlay != null){
			this.overlay.remove();
		}

		if(this.mortgageCalculator != null){

			var bodyObj = document.getElementsByTagName("body").item(0);

			this.mortgageCalculator.removeFromElement(bodyObj);
			this.mortgageCalculator = null;

		}

	}


	// style methods

	this.applyDefaultStyles = function(){


	}



	// Display methods

	this.loadSearchResults = function(){

		this.clearList();

		this.offset = 0;

		this.itemArray = new Array();

		if(RPWSearchSocket != null){

			this.recordTotal = RPWSearchSocket.getResultTotal();

			this.updateStatus();

			if(this.recordTotal == 0){
				this.onEmptyResultSet();
			}else{
				this.hideNoResultMessage();
				this.clearList();
			}

		}

		this.resultsDisplayed = true;

		this.loadResultBatch();

	}



	this.loadPageSet = function(offset){
		this.offset = offset*this.displayCount;
		this.loadResultBatch();
	}

	this.nextPageSet = function(){
		this.offset += this.displayCount;
		this.loadResultBatch();
	}

	this.prevPageSet = function(){
		this.offset -= this.displayCount;
		this.offset = Math.max(this.offset,0);
		this.loadResultBatch();
	}

	this.lastPageSet = function(){
		this.offset = Math.floor(this.recordTotal/this.displayCount)*this.displayCount;
		this.loadResultBatch();
	}

	this.firstPageSet = function(){
		this.offset = 0;
		this.loadResultBatch();
	}

	this.loadResultBatch = function(){

		if(RPWSearchSocket != null){

			this.parentObj.showLoadingGraphic();

			var thisObj = this;

			var onLoad = function(data){ thisObj.addResultBatch(data) };

			RPWSearchSocket.getResultSet(this.offset,this.displayCount,onLoad);

		}
	}

	this.addResultBatch = function(data){

		if (this.getAttribute("RPWPropertyListObject.usePageSets")) {
			this.clearList();
		}


		if(this.offset < this.recordTotal){


			if(data.properties != null){

				for(var i=0;i<data.properties.length;i++){

					this.addItem(data.properties[i]);

				}

			}

			if (!this.getAttribute("RPWPropertyListObject.usePageSets")) {
				this.offset += this.displayCount;
			}

			this.updateStatus();

			if (this.getAttribute("RPWPropertyListObject.usePageSets")) {
				this.updateNavigation();
			}

		}

		document.location = "#"+this.parentObj.domElement.getAttribute("id");

		this.parentObj.hideLoadingGraphic();

	}

	this.onEmptyResultSet = function(){

		this.clearList();

		if (this.getAttribute("RPWPropertyListObject.usePageSets")) {
			this.updateNavigation();
		}

		if(this.getAttribute("RPWPropertyListObject.noResultsMessage")){

			this.listObject.style.display = "none";

			if(this.noResultObject == null){
				this.noResultObject = document.createElement("div");
				this.noResultObject.className = "noResults";
				this.noResultObject.innerHTML = urlDecode(this.getAttribute("RPWPropertyListObject.noResultsMessage"));
				this.listContainer.appendChild(this.noResultObject);

			}

			this.noResultObject.style.display = "block";

		}
	}

	this.hideNoResultMessage = function(){
		if (this.noResultObject != null) {
			this.noResultObject.style.display = "none";
		}
		this.listObject.style.display = "block";
	}

	this.updateStatus = function(){

		var str = "";

		if(this.recordTotal == 0){
			str += "No properties found";
		}else if (this.getAttribute("RPWPropertyListObject.usePageSets")) {

			str += "Displaying page " + ((this.offset/this.displayCount)+1) + " of ";

			str += Math.ceil(this.recordTotal/this.displayCount);// display total
		} else {
			if (this.itemArray.length > 0) {
				str += "Displaying " + this.itemArray.length + " of ";
			}

			str += this.recordTotal + ((this.recordTotal == 1) ? " property" : " properties");// display total
		}

		this.totalDisplay.innerHTML = str;


	}

	this.updateNavigation = function(){

		this.clearNavigation();
		var pageLink;
		var clone;
		var thisObj = this;

		if (this.recordTotal > this.displayCount) {

			if (this.offset > 0) {
				/*pageLink = this.navigationElementTop.addElement("a", "&#171;");
				pageLink.setAttribute("href", "javascript:void(0);");
				pageLink.onclick = function(){
					thisObj.firstPageSet();
				};
				clone = pageLink.cloneNode(true);
				clone.onclick = function(){
					thisObj.firstPageSet();
				};
				this.navigationElementBottom.appendChild(clone);*/

				pageLink = this.navigationElementTop.addElement("a", "<");
				pageLink.setAttribute("href", "javascript:void(0);");
				pageLink.onclick = function(){
					thisObj.prevPageSet();
				};
				clone = pageLink.cloneNode(true);
				clone.onclick = function(){
					thisObj.prevPageSet();
				};
				this.navigationElementBottom.appendChild(clone);
			}

			var pageOffset = Math.floor((this.offset / this.displayCount) / 20) * 20;

			for (var i = pageOffset; i < this.recordTotal / this.displayCount && i < 20 + pageOffset; i++) {

				if (i == this.offset / this.displayCount) {
					this.navigationElementTop.addElement("strong", (i + 1));
					this.navigationElementBottom.addElement("strong", (i + 1));
				} else {
					pageLink = this.navigationElementTop.addElement("a", (i + 1));
					pageLink.setAttribute("href", "javascript:void(0);");
					pageLink.setAttribute("index", i);
					pageLink.onclick = function(){
						thisObj.loadPageSet(this.getAttribute("index"));
					};

					clone = pageLink.cloneNode(true);
					clone.onclick = function(){
						thisObj.loadPageSet(this.getAttribute("index"));
					};
					this.navigationElementBottom.appendChild(clone);
				}

			}

			if (this.offset < this.recordTotal - this.displayCount) {

				pageLink = this.navigationElementTop.addElement("a", ">");
				pageLink.setAttribute("href", "javascript:void(0);");
				pageLink.onclick = function(){
					thisObj.nextPageSet();
				};

				clone = pageLink.cloneNode(true);
				clone.onclick = function(){
					thisObj.nextPageSet();
				};
				this.navigationElementBottom.appendChild(clone);

				/*pageLink = this.navigationElementTop.addElement("a", "&#187;");
				pageLink.setAttribute("href", "javascript:void(0);");
				pageLink.onclick = function(){
					thisObj.lastPageSet();
				};

				clone = pageLink.cloneNode(true);
				clone.onclick = function(){
					thisObj.lastPageSet();
				};
				this.navigationElementBottom.appendChild(clone);*/
			}

		}

	}

	this.clearNavigation = function(){

		if(this.navigationElementTop != null){
			this.navigationElementTop.clearContents();
		}
		if(this.navigationElementBottom != null){
			this.navigationElementBottom.clearContents();
		}
	}


	this.changeOrder = function(select){

		if(RPWSearchSocket != null){
			switch(select.options[select.selectedIndex].value){

			case "pprice desc":
				RPWSearchSocket.setSearchSetting("order_by","pprice");
				RPWSearchSocket.setSearchSetting("order_desc",1);
				break;

			default:
				RPWSearchSocket.setSearchSetting("order_by","pprice");
				RPWSearchSocket.setSearchSetting("order_desc",0);
				break;

			}

			this.parentObj.showLoadingGraphic();
			RPWSearchSocket.doSearch();

		}
	}


	// Item methods


	this.addItem = function(dataObject){

		var listItem = new RPWPropertyListItemObject(dataObject);
		listItem.setParent(this);

		listItem.displayContent();

		this.listObject.appendChild(listItem.getDOMElement());

		this.itemArray.push(listItem);

		return listItem;

	}

	this.removeItem = function(dataObject){

		for(var i in this.itemArray){

			if(this.itemArray[i].dataObject.db == dataObject.db && this.itemArray[i].dataObject.pcode == dataObject.pcode){
				this.listObject.removeChild(this.itemArray[i].getDOMElement());
				this.itemArray.splice(i,1);
				return;
			}

		}

	}

	this.showDetails = function(listItem){

		// create details object

		var detailsObj = new RPWPropertyDetailsObject(listItem.dataObject);
		detailsObj.setParent(this);

		detailsObj.displayContent();

		this.listObject.insertBefore(detailsObj.getDOMElement(),listItem.getDOMElement());

		this.listObject.removeChild(listItem.getDOMElement());

		for(var i in this.itemArray){

			if(this.itemArray[i] == listItem){
				this.itemArray.splice(i,1,detailsObj);
				return;
			}

		}

	}

	this.hideDetails = function(detailsItem){

		// create details object

		var listItem = new RPWPropertyListItemObject(detailsItem.dataObject);
		listItem.setParent(this);

		listItem.displayContent();

		this.listObject.insertBefore(listItem.getDOMElement(),detailsItem.getDOMElement());

		this.listObject.removeChild(detailsItem.getDOMElement());

		for(var i in this.itemArray){

			if(this.itemArray[i] == detailsItem){
				this.itemArray.splice(i,1,listItem);
				return;
			}

		}

	}

	this.showRepayments = function(){

		if(this.getAttribute("RPWPropertyListObject.showMortgageRepayments")){

			for(var i in this.itemArray){

				this.itemArray[i].showRepayments();

			}

		}

	}


	this.markItemAsSaved = function(dataObject,saved){

		for(var i in this.itemArray){

			if(this.itemArray[i].dataObject.db == dataObject.db && this.itemArray[i].dataObject.pcode == dataObject.pcode){
				this.itemArray[i].markAsSaved(saved);
				return;
			}

		}

	}

	this.collapseItems = function(){

		for(var i in this.itemArray){

			this.itemArray[i].hideDetails();

		}

	}

	this.setActiveProperty = function(propertyItem){
		this.activeProperty = propertyItem;
	}

	// DOM methods

	this.clearList = function(){

		if(this.listObject != null){

			if (this.listObject.hasChildNodes() ){
	  			while(this.listObject.childNodes.length >= 1 ){
	       			this.listObject.removeChild(this.listObject.firstChild);
			    }
			}

			this.setScroll(0);
		}

	}


	// Scroll methods

	this.onListScroll = function(div){

		if(div.scrollTop + div.clientHeight >= div.scrollHeight){
			this.loadResultBatch();
		}

	}

	this.setScroll = function(pos){

		this.listContainer.domElement.scrollTop = pos;

	}

	// constructor

	this.RPWPropertyListObject();

}

RPWPropertyListObject.inherits(DisplayObject);

function RPWPropertyListItemObject(dataObject){

	DisplayObject.call(this);

	// create container

	// sub-elements
	this.dataObject = dataObject;

	this.titleElement = null;
	this.priceElement = null;
	this.imageElement = null;
	this.referenceElement = null;
	this.repaymentElement = null;
	this.statusElement = null;
	this.descriptionElement = null;
	this.roomListElement = null;
	this.accommSummaryElement = null;
	this.roomXRoomElement = null;
	this.contactElement = null;
	this.contactElement = null;
	this.addThisButtonElement = null;

	this.optionButtonsElement = null;
	this.detailsButton = null;
	this.saveButton = null;

	this.detailsShown = false;
	this.fullDetailsElement = null;


	// set default settings

	this.moreDetailsText = "More details";


	this.RPWPropertyListItemObject = function(){

		this.createDOMElement("li","property listItem "+this.dataObject.ocode);

	}

	this.getItemOrder = function(){
		return (this.getAttribute("RPWPropertyListItemObject.itemOrder")) ? this.getAttribute("RPWPropertyListItemObject.itemOrder") : "buttons,image,title,reference,status,rooms,description,contact,addThis";
	}


	this.displayContent = function(){

		var itemOrder = this.getItemOrder();

		itemOrder = itemOrder.split(",");

		for (var i in itemOrder) {


			switch(itemOrder[i]){

				case "details":

					this.detailsButton = this.getDetailsButtonElement();

					if(this.detailsButton != null){
						this.domElement.appendChild(this.detailsButton);
					}

					break;


				case "buttons":

					// add option buttons
					this.optionButtonsElement = this.getOptionButtonsElement();
					this.domElement.appendChild(this.optionButtonsElement);

					break;

				case "image":

					// add image
					this.imageElement = this.getImageElement();

					if (this.imageElement != null) {
						this.domElement.appendChild(this.imageElement);
					}

					break;

				case "title":

					// add title
					this.titleElement = this.getTitleElement();
					this.domElement.appendChild(this.titleElement);

					// add repayments

					this.repaymentElement = this.getRepaymentElement();

					if (this.repaymentElement != null) {
						this.domElement.appendChild(this.repaymentElement);
						this.showRepayments();
					}

					break;

				case "reference":

					// add reference

					if (this.getAttribute("RPWPropertyListObject.showPropertyReference")) {

						this.referenceElement = this.getReferenceElement();

						if (this.referenceElement != null) {
							this.domElement.appendChild(this.referenceElement);
						}
					}

					break;

				case "status":

					this.statusElement = this.getStatusElement();

					if (this.statusElement != null) {
						this.domElement.appendChild(this.statusElement);
					}

					break;

				case "rooms":

					// add room list
					this.roomListElement = this.getRoomListElement();

					if (this.roomListElement != null) {
						this.domElement.appendChild(this.roomListElement);
					}

					break;

				case "description":

					// add description
					this.descriptionElement = this.getDescriptionElement();

					if (this.descriptionElement != null) {
						this.domElement.appendChild(this.descriptionElement);
					}

					break;

				case "accommodation summary":

					// add description
					this.accommSummaryElement = this.getAccommSummaryElement();

					if (this.accommSummaryElement != null) {
						this.domElement.appendChild(this.accommSummaryElement);
					}

					break;

				case "room by room":

					// add description
					this.roomXRoomElement = this.getRoomXRoomElement();

					if (this.roomXRoomElement != null) {
						this.domElement.appendChild(this.roomXRoomElement);
					}

					break;

				case "contact":

					// add contact details

					this.contactElement = this.getContactElement();

					if (this.contactElement != null) {
						this.domElement.appendChild(this.contactElement);
					}

					break;

				case "addThis":
					// add 'add this'
					if (this.getAttribute("RPWPropertyListObject.showAddThis")) {

						this.addThisButtonElement = this.getAddThisButtonElement();

						if (this.addThisButtonElement != null) {
							this.domElement.appendChild(this.addThisButtonElement);
						}
					}

					break;

			}

		}


		// apply styles
		this.applyDefaultStyles();

	}

	this.showMortgageCalculator = function(){

		if(price = this.getPrice()){
			var parentObj = this.getParent();
			parentObj.showMortgageCalculator(price);
		}
	}


	this.showViewingRequestForm = function(){

		var parentObj = this.getParent();


		var thisObj = this;
		var removeFunc = function(){ thisObj.removeViewingRequestForm(); };

		this.overlay = parentObj.parentObj.addOverlay(removeFunc);
		this.overlay.setStyle("z-index",1000);

		this.viewingRequestForm = new RPWViewingRequestFormObject();

		this.viewingRequestForm.setParent(this);

		if(this.getAttribute("RPWViewingRequestFormObject.viewingFormTitle")){
			this.viewingRequestForm.title = this.getAttribute("RPWViewingRequestFormObject.viewingFormTitle");
		}
		if(this.getAttribute("RPWViewingRequestFormObject.viewingFormIntro")){
			this.viewingRequestForm.introStr = this.getAttribute("RPWViewingRequestFormObject.viewingFormIntro");
		}
		if(this.getAttribute("RPWViewingRequestFormObject.formFields")){
			this.viewingRequestForm.formFields = this.getAttribute("RPWViewingRequestFormObject.formFields");
		}

		if(this.getAttribute("RPWViewingRequestFormObject.viewingRequestAction")){
			this.viewingRequestForm.action = this.getAttribute("RPWViewingRequestFormObject.viewingRequestAction");
		}

		this.viewingRequestForm.pcode = this.dataObject.pcode;
		this.viewingRequestForm.rps = this.dataObject.db;

		this.viewingRequestForm.address = this.dataObject.address;

		this.viewingRequestForm.onRemoveFunction = removeFunc;

		this.viewingRequestForm.setStyle("z-index",1020);

		var bodyObj = document.getElementsByTagName("body").item(0);

		this.viewingRequestForm.appendToElement(bodyObj);

		this.viewingRequestForm.displayContent();

		return this.viewingRequestForm;


	}

	this.removeViewingRequestForm = function(){

		if(this.overlay != null){
			this.overlay.remove();
		}

		if(this.viewingRequestForm != null){

			var bodyObj = document.getElementsByTagName("body").item(0);

			this.viewingRequestForm.removeFromElement(bodyObj);
			this.viewingRequestForm = null;

		}

	}


	this.getTitleElement = function(){

		var element = document.createElement("h4");


		if(this.getAttribute("RPWPropertyListObject.showMortgageCalculator")){// add mortgage calculator link

			var regex = /[^\d\.]/g;
			var price = String(this.dataObject.price).replace(regex,"");

			if(!isNaN(parseFloat(price))){

				this.priceElement = document.createElement("a");
				this.priceElement.className = "price";
				this.priceElement.setAttribute("href","javascript:void(0);");
				this.priceElement.setAttribute("title","Click to calculate mortgage repayments.");

				var thisObj = this;
				this.priceElement.onclick = function(){thisObj.showMortgageCalculator();};

			}

		}

		if(this.priceElement == null){
			this.priceElement = document.createElement("strong");
		}

		this.priceElement.innerHTML = this.dataObject.price;

		element.appendChild(this.priceElement);

		var space = document.createTextNode(" ");
		element.appendChild(space);

		var address = document.createTextNode(this.dataObject.address);
		element.appendChild(address);

		return element;

	}

	this.getImageElement = function(){

		if(this.dataObject.images != null){

			var thisObj = this;

			var element = document.createElement("a");
			element.setAttribute("href","javascript:void(0);");

			if(this.getAttribute("RPWPropertyListItemObject.clickImageForSlideshow")){

				element.onclick = function(){thisObj.showSlideShow(); this.blur();};
				element.setAttribute("title","Click for slideshow");

			}else{

				element.onclick = function(){thisObj.showDetails(); this.blur();};
				element.setAttribute("title","Click to show full details");

			}


			element.className = "thumbnail";

			element.setAttribute("style","cursor:pointer;");

			var img  = document.createElement("img");
			img.setAttribute("width",this.getAttribute("thumbnailWidth"));
			img.setAttribute("height",this.getAttribute("thumbnailHeight"));
			img.setAttribute("src",httpRoot+"index.php?action=getthumbnail&filepath="+this.dataObject.images[0].filepath+"&width="+this.getAttribute("thumbnailWidth")+"&height="+this.getAttribute("thumbnailHeight")+"&quality=75&crop=1");

			element.appendChild(img);

			return element;

		}

		return null;

	}

	this.getDescriptionElement = function(){

		if(this.dataObject.description != null){

			var element = document.createElement("p");

			element.className = "description";

			var text = String(this.dataObject.description).stripHTMLTags();

			var limit =  this.getAttribute("RPWPropertyListItemObject.descriptionLimit");

			if(limit != null && limit != 0 && text.length > limit){

				// cut to num characters
				text =  String(text).substr(0,limit);
				// cut to last word ending
				text = text.substr(0,text.lastIndexOf(" "))+" . . .";

			}

			element.innerHTML = text;

			return element;

		}

		return null;

	}

	this.getPrice = function(){

		var pattern = /-.*$/g;// remove 'to' price

		var priceString = String(this.dataObject.price).replace(pattern, '');

		pattern = /[^\d\.]/g;

		var amount = parseFloat(priceString.replace(pattern, ''));

		if (!isNaN(amount)) {
			return amount;
		}

		return null;

	}

	this.getRepaymentElement = function(){


		var element = document.createElement("p");
		element.className = "mortgageRepayment";
		element.style.display = "none";

		return element;


		return null;

	}

	this.showRepayments = function(){

		if (this.getAttribute("RPWPropertyListObject.showMortgageRepayments")) {

			if (amount = this.getPrice()) {

				var text = "";

				if (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit") != null) {// user specified deposit - we can display
					var deposit = (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit")) ? RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit") : amount * 0.15;
					var term = (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.term")) ? RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.term") : 25;
					var rate = (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.interestRate")) ? RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.interestRate") : RPWSearchSocket.getSearchSetting("interestRate");
					amount = amount - deposit;

					var rate = rate / 100;
					var p = ((amount * rate) / 12) * (1 / (1 - (Math.pow(1 / (1 + rate), term))));


					if (p > 0) {

						text = "Repayments &pound;" + numberFormat(p, 0) + " pcm";

					}

				}

				if(text == ""){
					text = "Click here to calculate mortgage repayments";
				}

				// clear node
				if (this.repaymentElement.hasChildNodes()) {
					while (this.repaymentElement.childNodes.length >= 1) {
						this.repaymentElement.removeChild(this.repaymentElement.firstChild);
					}
				}

				var a = document.createElement("a");
				a.setAttribute("href", "javascript:void(0);");
				a.setAttribute("title", "Click to calculate.");

				var thisObj = this;
				a.onclick = function(){
					thisObj.showMortgageCalculator();
				};

				a.innerHTML = text;
				this.repaymentElement.appendChild(a);
				this.repaymentElement.style.display = "block";



			}

		}

	}

	this.getAddThisButtonElement = function(){

		var permalinkPage = this.getAttribute("RPWPropertyListObject.permalinkPage");

		if(permalinkPage != null){

			var url = permalinkPage+"property-"+this.dataObject.type+"-"+this.dataObject.db+"-"+this.dataObject.pcode;

			var element = document.createElement("div");
			var addThis = document.createElement("a");
			addThis.className = "addThis";
			/*var div = document.createElement("div");
			div.className = "addthis_toolbox addthis_default_style";
			div.setAttribute("addthis:url",url);
			div.setAttribute("addthis:title",this.dataObject.address);

			div.innerHTML = "<a href=\"http://www.addthis.com/bookmark.php?v=250&amp;pub=xa-4ae181590fd13212\" class=\"addthis_button_compact\">Share</a>  <script type=\"text/javascript\"> var addthis_share = { url: '"+url+"', title: '"+this.dataObject.address+"' } </script>  <span class=\"addthis_separator\">|</span> <a class=\"addthis_button_facebook\"></a> <a class=\"addthis_button_email\"></a> <a class=\"addthis_button_favorites\"></a> <a class=\"addthis_button_print\"></a>";
			element.appendChild(div);

			var script = document.createElement("script");
			script.setAttribute("type","text/javascript");
			script.setAttribute("src","http://s7.addthis.com/js/250/addthis_widget.js#pub=xa-4ae181590fd13212");

			element.appendChild(script);*/

			element.appendChild(addThis);
			addthis.button(addThis, {ui_click: true}, {url: url, title: this.dataObject.address});

			return element;
		}

		return null;

	}



	this.getReferenceElement = function(){

		var element = document.createElement("p");
		element.className = "reference";
		element.innerHTML = "Ref: <strong>" + this.dataObject.pcode + "</strong>";

		return element;

	}

	this.getContactElement = function(){

		if (this.getAttribute("RPWPropertyListObject.showOfficeContacts")) {

			if (this.dataObject.office != null) {

				var element = document.createElement("p");
				element.className = "contacts";
				element.innerHTML = "<strong>Contact:</strong> <span class=\"office\">" + this.dataObject.office.name + "</span> <span class=\"telephone\">" + this.dataObject.office.telephone + "</span> ";

				if (this.dataObject.office.email != null) {
					var link = document.createElement("a");
					link.setAttribute("href", "#");
					link.innerHTML = this.dataObject.office.email;
					link.className = "email";
					var thisObj = this;
					link.onclick = function(){
						thisObj.showViewingRequestForm();
					}
					element.appendChild(link);
				}

				return element;

			}

		}


	}

	this.getStatusElement = function(){

		if (this.dataObject.status != null) {
			var element = document.createElement("h5");
			element.className = "status";
			element.innerHTML = this.dataObject.status;

			return element;

		}

		return null;

	}

	this.getRoomListElement = function(){

		if(this.dataObject.rooms != null){

			var element = document.createElement("ul");

			element.className = "roomList";

			var roomItem;

			for(var i in this.dataObject.rooms){

				roomItem = document.createElement("li");
				roomItem.title = this.dataObject.rooms[i]+" "+i;
				roomItem.className = String(i).replace(/\(?s\)?$/gi,"").toLowerCase();
				roomItem.innerHTML = this.dataObject.rooms[i]+" <span>"+i+"</span>";

				element.appendChild(roomItem);

			}

			var land = this.dataObject.land;

			if(this.getAttribute("RPWPropertyListObject.showLandInRoomList") && land != null){

				roomItem = document.createElement("li");
				roomItem.title = "Land";
				roomItem.className = "land";
				roomItem.innerHTML = land+" <span>"+(this.dataObject.landUnit)+((this.dataObject.land == 1) ? "" : "s")+"</span>";

				element.appendChild(roomItem);

			}

			return element;

		}

		return null;

	}



	// BUTTONS

	this.getOptionButtonsElement = function(){

		// add details button

		var element = document.createElement("p");
		element.className = "optionButtons";

		if(String(this.getItemOrder()).indexOf("details") == -1){// details buttons hasn't been set elsewhere - include it.

			this.detailsButton = this.getDetailsButtonElement();

			if(this.detailsButton != null){
				element.appendChild(this.detailsButton);
			}

		}

		var viewingButton = this.getViewingButtonElement();

		if(viewingButton != null){
			element.appendChild(document.createTextNode(" "));
			element.appendChild(viewingButton);
		}

		var pdfButton = this.getPrintDetailsButtonElement();

		if(pdfButton != null){
			element.appendChild(document.createTextNode(" "));
			element.appendChild(pdfButton);
		}

		var permalinkButton = this.getPermalinkButtonElement();

		if(permalinkButton != null){
			element.appendChild(document.createTextNode(" "));
			element.appendChild(permalinkButton);
		}


		if (!this.getAttribute("RPWPropertyListItemObject.clickImageForSlideshow")) {
			var slideShowButton = this.getSlideShowButtonElement();
			 if(slideShowButton != null){
				 element.appendChild(document.createTextNode(" "));
	 			element.appendChild(slideShowButton);
	 		}
		}

		var floorplanButton = this.getFloorplanButtonElement();

		if(floorplanButton != null){
			element.appendChild(document.createTextNode(" "));
			element.appendChild(floorplanButton);
		}

		var epcButton = this.getEPCButtonElement();

		if(epcButton != null){
			element.appendChild(document.createTextNode(" "));
			element.appendChild(epcButton);
		}

		var mapButton = this.getMapButtonElement();

		if(mapButton != null){
			element.appendChild(document.createTextNode(" "));
			element.appendChild(mapButton);
		}

		var emailDetailsButton = this.getEmailDetailsButtonElement();

		if(emailDetailsButton != null){
			element.appendChild(document.createTextNode(" "));
			element.appendChild(emailDetailsButton);
		}

		this.saveButton = this.getSaveButtonElement();

		this.markAsSaved(this.parentObj.parentObj.propertyIsSaved(this.dataObject));

		if(this.saveButton != null){
			element.appendChild(document.createTextNode(" "));
			element.appendChild(this.saveButton);
		}

		return element;

	}

	this.getDetailsButtonElement = function(){

		var element = document.createElement("a");
		element.setAttribute("href","javascript:void(0);");
		element.className = "pOptionButton showDetails";

		var thisObj = this;
		element.onclick = function(){thisObj.showDetails(); this.blur();};

		var text = (this.getAttribute("RPWPropertyListObject.moreDetailsLabel")) ? this.getAttribute("RPWPropertyListObject.moreDetailsLabel") : "More details";

		element.innerHTML = "<span>"+text+"</span>";
		element.title = text;

		return element;

	}

	this.getSaveButtonElement = function(){

		var element = document.createElement("a");
		element.setAttribute("href","javascript:void(0);");

		var thisObj = this;
		element.onclick = function(e){thisObj.toggleSaved(e); this.blur();};

		element.className = "pOptionButton saveToShortlist";

		var text;

		if(this.getAttribute("RPWPropertyListObject.shortListLabels")){
			var labels = this.getAttribute("RPWPropertyListObject.shortListLabels").split(",");
			text = labels[0];
		}else{
			text = "Save to shortlist";
		}

		element.innerHTML = "<span>"+text+"</span>";
		element.title = text;


		return element;

	}

	this.getPrintDetailsButtonElement = function(){

		if(this.dataObject.pdf != null){

			var element = document.createElement("a");
			element.setAttribute("href",httpRoot+this.dataObject.pdf);
			element.setAttribute("target","RPWPrintDetails");


			element.className = "pOptionButton printDetails";

			var text = (this.getAttribute("RPWPropertyListObject.printDetailsLabel")) ? this.getAttribute("RPWPropertyListObject.printDetailsLabel") : "Printable details";

			element.innerHTML = "<span>"+text+"</span>";
			element.title = "Printable details";

			return element;

		}

		return null;

	}

	this.getPermalinkButtonElement = function(){

		if (this.getAttribute("RPWPropertyListObject.showPermalink")) {

			var permalinkPage = this.getAttribute("RPWPropertyListObject.permalinkPage");

			if (permalinkPage != null) {

				var element = document.createElement("a");

				element.setAttribute("href", permalinkPage+"property-"+this.dataObject.type+"-"+this.dataObject.db+"-"+this.dataObject.pcode);
				element.setAttribute("target","RPWPermalink");
				element.className = "pOptionButton permaLink";


				var text = (this.getAttribute("RPWPropertyListObject.permalinkLabel")) ? this.getAttribute("RPWPropertyListObject.permalinkLabel") : "Permalink";

				element.innerHTML = "<span>" + text + "</span>";
				element.title = text;

				return element;

			}

		}
	}

	this.getSlideShowButtonElement = function(){

		if(this.dataObject.images != null){

			var element = document.createElement("a");
			element.setAttribute("href","javascript:void(0);");

			var thisObj = this;

			element.onclick = function(){thisObj.showSlideShow(); this.blur();};

			element.className = "pOptionButton slideShow";

			var text = (this.getAttribute("RPWPropertyListObject.slideShowLabel")) ? this.getAttribute("RPWPropertyListObject.slideShowLabel") : "Slide show";

			element.innerHTML = "<span>"+text+"</span>";
			element.title = text;

			return element;

		}

		return null;

	}

	this.getFloorplanButtonElement = function(){

		if(this.dataObject.floorplans != null){

			var element = document.createElement("a");
			element.setAttribute("href","javascript:void(0);");

			var thisObj = this;

			element.onclick = function(){thisObj.showFloorplan(); this.blur();};

			element.className = "pOptionButton floorplan";

			var text;

			if(this.getAttribute("RPWPropertyListObject.floorplanLabels")){
				var labels = this.getAttribute("RPWPropertyListObject.floorplanLabels").split(",");
				text = (this.dataObject.floorplans.length > 1)  ? labels[1] : labels[0] ;
			}else{
				text = (this.dataObject.floorplans.length > 1)  ? "Floorplans" : "Floorplan";
			}

			element.innerHTML = "<span>"+text+"</span>";
			element.title = text;

			return element;

		}

		return null;

	}

	this.getEPCButtonElement = function(){

		if(this.dataObject.epc != null){

			var element = document.createElement("a");
			element.setAttribute("href","javascript:void(0);");

			var thisObj = this;

			element.onclick = function(){thisObj.showEPC(); this.blur();};

			element.className = "pOptionButton epc";

			var text = (this.getAttribute("RPWPropertyListObject.epcLabel")) ? this.getAttribute("RPWPropertyListObject.epcLabel") : "EPC";

			element.innerHTML = "<span>"+text+"</span>";
			element.title = text;

			return element;

		}

		return null;

	}

	this.getMapButtonElement = function(){

		if(this.dataObject.latitude != null && this.dataObject.longitude != null){

			var element = document.createElement("a");
			element.setAttribute("href","javascript:void(0);");

			var thisObj = this;

			element.onclick = function(){thisObj.showOnMap(); this.blur();};

			element.className = "pOptionButton map";

			var text = (this.getAttribute("RPWPropertyListObject.mapLabel")) ? this.getAttribute("RPWPropertyListObject.mapLabel") : "Show on map";

			element.innerHTML = "<span>"+text+"</span>";
			element.title = text;

			return element;

		}

		return null;

	}

	this.getEmailDetailsButtonElement = function(){

		var permalinkPage = this.getAttribute("RPWPropertyListObject.permalinkPage");

		if(permalinkPage != null){

			var element = document.createElement("a");

			var link = "mailto:?subject="+urlEncode(this.dataObject.address)+"&body="+urlEncode(permalinkPage+"property-"+this.dataObject.type+"-"+this.dataObject.db+"-"+this.dataObject.pcode)
			element.setAttribute("href",link);

			var thisObj = this;

			element.className = "pOptionButton emailDetails";

			var text = (this.getAttribute("RPWPropertyListObject.emailDetailsLabel")) ? this.getAttribute("RPWPropertyListObject.emailDetailsLabel") : "Share";

			element.innerHTML = "<span>"+text+"</span>";
			element.title = "E-mail this property to a friend";

			return element;

		}

		return null;

	}

	this.getViewingButtonElement = function(){

		if (this.getAttribute("RPWPropertyListObject.showBookViewing") && this.dataObject.office.email != null) {

			var element = document.createElement("a");

			var link = this.getViewingEmailLink();

			element.setAttribute("href", "javascript:void(0);");

			var thisObj = this;

			element.onclick = function(){
				thisObj.showViewingRequestForm();
			}

			element.className = "pOptionButton bookViewing";

			var text = (this.getAttribute("RPWPropertyListObject.bookViewingLabel")) ? this.getAttribute("RPWPropertyListObject.bookViewingLabel") : "Book viewing";

			element.innerHTML = "<span>" + text + "</span>";
			element.title = text;

			return element;

		}


		return null;

	}

	this.getViewingEmailLink = function(){
		if (this.dataObject.office.email != null) {
			var message;
			if(this.getAttribute("RPWPropertyListObject.viewingMailBody") != null){
				message =  this.getAttribute("RPWPropertyListObject.viewingMailBody").replace(/%25%25pcode%25%25/g,this.dataObject.pcode);
				message =  message.replace(/%25%25address%25%25/g,urlEncode(this.dataObject.address));
			}else{
				message = urlEncode("Please arrange a viewing for this property (Ref: " + this.dataObject.pcode + ")\n\nMy telephone number is: ");
			}
			return "mailto:" + this.dataObject.office.email + "?subject=" + urlEncode(this.dataObject.address) + "&body=" + message.replace(/%C2%A3/g, "%A3");
		}

		return null;
	}

	this.applyDefaultStyles = function(){



	}

	// User methods

	this.showDetails = function(){

		if(parentObj = this.getParent()){

			parentObj.showDetails(this);

			if(RPWSearchSocket != null){
				RPWSearchSocket.saveWebStat(this.dataObject.type+"-"+this.dataObject.db+"-"+this.dataObject.pcode);
			}

		}

	}


	this.toggleSaved = function(e){

		if(!this.parentObj.parentObj.propertyIsSaved(this.dataObject)){


			this.parentObj.parentObj.saveProperty(this.dataObject);

		}else{

			this.parentObj.parentObj.removeSavedProperty(this.dataObject);

		}

	}

	this.markAsSaved = function(saved){

		if(this.getAttribute("RPWPropertyListObject.shortListLabels")){
			var labels = this.getAttribute("RPWPropertyListObject.shortListLabels").split(",");
			var save = labels[0];
			var remove = labels[1];
		}else{
			var save = "Save to shortlist";
			var remove = "Remove from shortlist";
		}
		if(saved){
			this.saveButton.className = "pOptionButton removeFromShortlist";
			this.saveButton.title = remove;
			this.saveButton.innerHTML = "<span>"+remove+"</span>";
		}else{
			this.saveButton.className = "pOptionButton saveToShortlist";
			this.saveButton.title = save;
			this.saveButton.innerHTML = "<span>"+save+"</span>";
		}
	}


	this.showSlideShow = function(){
		this.parentObj.parentObj.showPropertySlideShow(this.dataObject);
	}

	this.showFloorplan = function(){
		this.parentObj.parentObj.showPropertySlideShow(this.dataObject,"floorplan");
	}

	this.showEPC = function(){
		this.parentObj.parentObj.showPropertySlideShow(this.dataObject,"epc");
	}

	this.showOnMap = function(){
		this.parentObj.parentObj.showPropertyOnMap(this.dataObject);
	}

	// init constructor

	this.RPWPropertyListItemObject();

}

RPWPropertyListItemObject.inherits(DisplayObject);
function RPWSavedPropertyListObject(){

	RPWPropertyListObject.call(this);
	
	this.getTotal = function(){
		this.totalDisplay.innerHTML = this.itemArray.length + ((this.itemArray.length == 1) ? " property" : " properties")+" saved";// display total
		return this.itemArray.length;
	}
	
	this.addOnScroll = function(){
		
		return;
	}
	
	this.getOrderSelectorElement = function(){
		return null;
	}
}

RPWSavedPropertyListObject.inherits(RPWPropertyListObject);


function RPWPropertyDetailsViewerObject(){

	RPWPropertyListObject.call(this);

	this.RPWPropertyDetailsViewerObject = function(){

		this.addCloseButton();
	}

	this.getTotal = function(){
		this.totalDisplay.innerHTML = this.itemArray.length + ((this.itemArray.length == 1) ? " property" : " properties")+" saved";// display total
		return this.itemArray.length;
	}

	this.addOnScroll = function(){

		return;
	}

	this.showPropertyDetails = function(dataObject){

		this.clearList();

		var listItem = new RPWPropertyDetailsObject(dataObject);
		listItem.setParent(this);

		listItem.displayContent();

		this.listObject.appendChild(listItem.getDOMElement());

		this.itemArray.push(listItem);

		return listItem;

	}

	this.addStatusBar = function(){
		// override
	}

	this.addCloseButton = function(){

		var closeButton = this.addElement("a");
		closeButton.setAttribute("href","javascript:void(0);");
		closeButton.className = "closeButton";
		closeButton.innerHTML = "<span>Close</span>";

		var thisObj = this;

		closeButton.onclick = function(){thisObj.remove();};

		return closeButton;

	}

	this.remove = function(){

		this.parentObj.removePropertyDetails();

	}

	this.getOrderSelectorElement = function(){
		return null;
	}

	RPWPropertyDetailsViewerObject();

}

RPWPropertyDetailsViewerObject.inherits(RPWPropertyListObject);


function RPWPropertyDetailsObject(dataObject){

	RPWPropertyListItemObject.call(this,dataObject);

	this.domElement.className = "property listItem details";

	// create container

	// sub-elements

	this.titleElement = null;
	this.priceElement = null;
	this.imageSet = null;
	this.mainImageContainer = null;// div to contain main image
	this.hoverImages = new Object();// object array to contain hover image objects

	this.optionButtonsElement = null;
	this.descriptionElement = null;
	this.roomListElement = null;
	this.accommSummaryElement = null;
	this.contactElement = null;

	this.featureDiv = null;


	this.getItemOrder = function(){
		return (this.getAttribute("RPWPropertyDetailsObject.itemOrder")) ? this.getAttribute("RPWPropertyDetailsObject.itemOrder") : "buttons,image,title,reference,status,rooms,description,accommodation summary,room by room,contact,addThis";
	}


	this.getImageElement = function(){

		if(this.dataObject.images != null){

			var imageTotal = this.dataObject.images.length

			// create images container

			var element = document.createElement("div");

			element.className = "imageSet";

			// get main image window

			var h = this.getAttribute("mainImageHeight");
			var totalWidth = Math.min(this.getAttribute("mainImageWidth"),h*2.5);
			var w = totalWidth;


			var thumbSize = ( h - this.getAttribute("imageMargin")*2)/4;

			if(imageTotal > 1){
				if(this.getAttribute("mainImageWidth") < w+(h/2)){// we have thumbnails, reduce image width
					w -= (this.getAttribute("RPWPropertyDetailsObject.thumbPanelWidth")) ? this.getAttribute("RPWPropertyDetailsObject.thumbPanelWidth") : (thumbSize + this.getAttribute("imageMargin"))*2;
				}else{
					totalWidth += (h/2);
				}
			}

			element.style.width = (totalWidth)+"px";
			element.style.height = h+"px";

			// add main image container

			this.mainImageContainer = document.createElement("div");
			this.mainImageContainer.style.cssFloat = "left";
			this.mainImageContainer.style.styleFloat = "left";
			this.mainImageContainer.style.position = "relative";

			var imageElement = document.createElement("img");
			imageElement.setAttribute("width",w);
			imageElement.setAttribute("height",h);
			imageElement.setAttribute("src",httpRoot+"index.php?action=getthumbnail&filepath="+this.dataObject.images[0].filepath+"&width="+w+"&height="+h+"&quality=80&crop=1");

			this.mainImageContainer.appendChild(imageElement);

			element.appendChild(this.mainImageContainer);

			if(imageTotal > 1){

				// add secondary images

				var thumbTotal = imageTotal -1;

				var maxThumbRows = 4;// maximum no. rows

				var columns = Math.ceil(thumbTotal/maxThumbRows);// allow max n rows

				var rows, tWidth, e;

				var extraSpaces = 0;

				if(columns == 1){
					rows = thumbTotal;
				}else{

					if(thumbTotal/columns == Math.round(thumbTotal/columns)){// total is divisible by columns

						rows = thumbTotal/columns;

					}else{

						rows = maxThumbRows;
						extraSpaces = (rows*columns)-thumbTotal; // extra spaces to be filled by expanding images

					}

				}

				var thumbnailApertureWidth = (totalWidth - w);// calculate width left for thumbnails

				var thumbnailWidth = Math.floor((thumbnailApertureWidth)/columns)-this.getAttribute("imageMargin");
				var thumbnailHeight = Math.floor((h + this.getAttribute("imageMargin"))/rows)-this.getAttribute("imageMargin");


				var thisObj = this;

				for(var i=1;i<imageTotal;i++){// loop through thumbnails, creating images

					tWidth = thumbnailWidth;

					if(extraSpaces > 0){// expand thumbnail width to take up extra spaces

						e = Math.min(extraSpaces,columns-1);// expand to max columns width
						tWidth += e*(thumbnailWidth+this.getAttribute("imageMargin"));
						extraSpaces -= e;

					}

					imageElement = document.createElement("img");
					imageElement.setAttribute("width",tWidth);
					imageElement.setAttribute("height",thumbnailHeight);
					imageElement.setAttribute("src",httpRoot+"index.php?action=getthumbnail&filepath="+this.dataObject.images[i].filepath+"&width="+tWidth+"&height="+thumbnailHeight+"&quality=70&crop=1");

					imageElement.style.margin = "0 0 "+this.getAttribute("imageMargin")+"px "+this.getAttribute("imageMargin")+"px";
					imageElement.style.cssFloat = "left";
					imageElement.style.styleFloat = "left";

					imageElement.setAttribute("index",i);

					imageElement.onmouseover = function(){thisObj.loadHoverImage(this.getAttribute("index"),w,h)};
					imageElement.onmouseout = function(){thisObj.unloadHoverImages()};

					element.appendChild(imageElement);

				}

			}

			return element;

		}

		return null;

	}

	this.loadHoverImage = function(i,w,h){

		this.unloadHoverImages(i);

		if(this.hoverImages[i] == null){// create new container

			this.hoverImages[i] =  new DisplayObject();
			this.hoverImages[i].createDOMElement("div");
			this.hoverImages[i].setStyle("position","absolute");
			this.hoverImages[i].setStyle("left",0);
			this.hoverImages[i].setStyle("top",0);
			this.hoverImages[i].setOpacity(0);

			this.hoverImages[i].addElement("img",null,"width",w,"height",h,"src",httpRoot+"index.php?action=getthumbnail&filepath="+this.dataObject.images[i].filepath+"&width="+w+"&height="+h+"&quality=80&crop=1");

			this.mainImageContainer.appendChild(this.hoverImages[i].getDOMElement());
		}

		this.hoverImages[i].changeOpacity(100);

	}

	this.unloadHoverImage = function(i){

		if(this.hoverImages[i] != null){
			this.hoverImages[i].changeOpacity(0);
		}

	}

	this.unloadHoverImages = function(omit){
		for(var i in this.hoverImages){
			if(i != omit && this.hoverImages[i].opacity > 0){
				this.hoverImages[i].changeOpacity(0);
			}
		}
	}

	this.getDetailsButtonElement = function(){

		var element = document.createElement("a");
		element.setAttribute("href","javascript:void(0);");
		element.className = "pOptionButton hideDetails";

		var thisObj = this;
		element.onclick = function(){thisObj.hideDetails(); this.blur();};

		element.innerHTML = "<span>Hide details</span>";
		element.title = "Hide details";

		return element;

	}

	this.hideDetails = function(){

		if(parentObj = this.getParent()){

			parentObj.hideDetails(this);

		}

	}


	this.getDescriptionElement = function(){

		var descriptionStr = null;

		if (this.getAttribute("RPWPropertyDetailsObject.descriptionVar") && this.dataObject[this.getAttribute("RPWPropertyDetailsObject.descriptionVar")] != null) {
			descriptionStr = this.dataObject[this.getAttribute("RPWPropertyDetailsObject.descriptionVar")];
		} else if (this.dataObject.description != null) {
			descriptionStr = this.dataObject.description;
		}

		if(descriptionStr){
			var element = document.createElement("p");

			element.className = "description";

			element.innerHTML = descriptionStr;

			return element;

		}

		return null;

	}

	this.getRoomListElement = function(){

		if(this.dataObject.rooms != null){

			var element = document.createElement("ul");

			element.className = "roomList";

			var roomItem;

			for(var i in this.dataObject.rooms){

				roomItem = document.createElement("li");
				roomItem.title = this.dataObject.rooms[i]+" "+i;
				roomItem.className = String(i).replace(/\(?s\)?$/gi,"").toLowerCase();
				roomItem.innerHTML = this.dataObject.rooms[i]+" <span>"+i+"</span>";

				element.appendChild(roomItem);

			}

			return element;

		}

		return null;

	}


	this.getRoomXRoomElement = function(){

		if(this.dataObject.roomXRoom != null){

			var element = document.createElement("ul");

			var roomNode

			for(var i in this.dataObject.roomXRoom){

				roomNode = document.createElement("li");

				roomNode.innerHTML = "";

				if(this.dataObject.roomXRoom[i].name != null && this.dataObject.roomXRoom[i].name != ""){
					roomNode.innerHTML += "<strong>"+this.dataObject.roomXRoom[i].name+"</strong>";
					if(this.dataObject.roomXRoom[i].size != null){
						roomNode.innerHTML += " <em>"+this.dataObject.roomXRoom[i].size+"</em>";
					}
					roomNode.innerHTML += "<br />";

				}

				if(this.dataObject.roomXRoom[i].description != null){
					roomNode.innerHTML += this.dataObject.roomXRoom[i].description;
				}

				element.appendChild(roomNode);

			}

			var div = document.createElement("div");
			div.className = "roomXRoom";

			var header = document.createElement("h5");
			header.innerHTML = "Accommodation";

			div.appendChild(header);
			div.appendChild(element);

			return div;

		}

		return null;


	}

	this.getAccommSummaryElement = function(){

		if(this.dataObject.accommodationSummary != null){

			var element = document.createElement("ul");

			var liElement;

			for(var i in this.dataObject.accommodationSummary){

				liElement = document.createElement("li");
				liElement.innerHTML = this.dataObject.accommodationSummary[i];
				element.appendChild(liElement);


			}

			var div = document.createElement("div");
			div.className = "accommodationSummary";

			var header = document.createElement("h5");
			header.innerHTML = "Property Features";

			div.appendChild(header);
			div.appendChild(element);

			return div;

		}

		return null;
	}

	this.getContactElement = function(){

		if(this.dataObject.office != null){

			var element = document.createElement("div");
			element.className = "contacts";

			element.innerHTML = "<h5>Contact:</h5><p>"+this.dataObject.office.name+"<br/>"+this.dataObject.office.address+"</p><p>"+this.dataObject.office.telephone+"</p>";

			if(this.dataObject.office.email != null){
				var p = document.createElement("p");
				var link = document.createElement("a");
				link.setAttribute("href","mailto:"+this.dataObject.office.email);
				link.innerHTML = this.dataObject.office.email;
				p.appendChild(link);
				element.appendChild(p);
			}

			return element;

		}

	}



	this.applyDefaultStyles = function(){

		this.setStyle("clear","left");


	}





}

RPWPropertyListItemObject.inherits(RPWPropertyListItemObject);
function RPWPropertySlideShowObject(dataObject){

	DisplayObject.call(this);
	
	// create container
	
	// sub-elements
	this.dataObject = dataObject;
	this.optionButtonsElement = null;
	this.saveButton = null;
	this.statusElement = null;
	
	this.imageArray = new Array();// array to store image elements, dataobjects and type (ieg image, floorplan, epc).
	this.imagePointer = 0;
	this.maxImageHeight = 600;
	this.maxImageWidth = 800;
	this.currentImageObject = null;
	
	this.imageTotal = 0;
	this.floorplanTotal = 0;
	
	this.onRemoveFunction = null;
	
	// 
	
	this.RPWPropertySlideShowObject = function(){
		
		// create array of images including floorplans and epc
		
		if(this.dataObject.images != null){
			for(var i in this.dataObject.images){
				this.imageArray[i] = this.dataObject.images[i];
				this.imageArray[i].type = "image";
			}
			
			this.imageTotal = this.dataObject.images.length;
		}
		
		var index;
		if(this.dataObject.floorplans != null){
			for(var i in this.dataObject.floorplans){
				index = this.imageArray.length;
				this.imageArray[index] = this.dataObject.floorplans[i];
				this.imageArray[index].type = "floorplan";
			}
			
			this.floorplanTotal = this.dataObject.floorplans.length;
		}

		if(this.dataObject.epc != null){
			index = this.imageArray.length;
			this.imageArray[index] = this.dataObject.epc;
			this.imageArray[index].type = "epc";
		}

		
		this.createDOMElement("div","RPWSlideShow");
		this.setStyle("background","#FFF");
		
		this.setPosition();
		
	}
	
	this.setPosition = function(){
		

		this.setStyle("position","absolute");

		// get image width and height
		
		var pageSizes = this.getPageSizeObject();
		
		var w = Math.min(pageSizes.windowWidth-20,800);
		var h = Math.min(pageSizes.windowHeight-20,660);
		
		this.maxImageWidth = w-40;
		this.maxImageHeight = h-90;
		
		this.setStyle("width",w+"px");
		this.setStyle("height",h+"px");
		
		var yScroll = this.getYScroll();
		
		var top = Math.max(0,yScroll + ((pageSizes.windowHeight - h) / 2));
		
		this.setStyle("top",top+"px");
		this.setStyle("left", Math.max(0,(pageSizes.pageWidth - w) / 2) + "px");
	
		
	}
	
	
	this.displayContent = function(type){
		
		this.clearContents();
		
		this.addCloseButton();
		
		this.optionButtonsElement = this.getOptionButtonsElement();
		this.domElement.appendChild(this.optionButtonsElement);
		
		//this.optionButtonsElement.style.position ="absolute";
		//this.optionButtonsElement.style.top = (this.maxImageHeight + 40)+"px";
		//this.optionButtonsElement.style.width = this.maxImageWidth+"px";
		//this.optionButtonsElement.style.left = "20px";
		//this.optionButtonsElement.style.textAlign = "center";

		this.addStatusElement();
		
		if(this.imageArray.length > 0){
			
			if(type != null){
				for(var i in this.imageArray){
					if(type == this.imageArray[i].type){
						this.loadImage(i);
						break;
					}
				}
			}else{
				this.loadImage(0);
			}
			
			// add navigation
			
			if(this.imageArray.length > 1){
				
				this.addNavigation();
				
				
			}
				
			
		}
	
	}
	
	this.remove = function(e){
		
		if(this.onRemoveFunction != null){
			this.onRemoveFunction(this);
		}
		
	}
	
	
	/// IMAGE METHODS
	
	this.loadImage = function(index){
		
		this.imagePointer = index;
		
		if(this.imageArray[index] != null){
			
			var newImage;
			
			switch(this.imageArray[index].type){
			
				case "floorplan":
					newImage = new RPWFloorplanViewerObject(this.imageArray[index]);
					if(this.floorplanTotal > 1){
						this.setStatus("Floorplan "+(index-this.imageTotal+1)+" of "+this.floorplanTotal);
					}else{
						this.setStatus("Floorplan");
					}
					break;
					
				case "epc":
					newImage = new RPWPropertyImageObject(this.imageArray[index]);
					this.setStatus("EPC");
					break;
				default:
					newImage = new RPWPropertyImageObject(this.imageArray[index]);
					this.setStatus("Image "+(index+1)+" of "+this.imageTotal);
			}
			
			//newImage.setStyle("position","absolute");
			//newImage.setStyle("left","20px");
			//newImage.setStyle("top","20px");
			newImage.setOpacity(0);
			newImage.displayContent(this.maxImageWidth, this.maxImageHeight, 0);
			
			newImage.appendToElement(this.domElement);
			
			newImage.changeOpacity(100);
			
			if(this.currentImageObject != null){
				
				var thisObj = this;
				var func = function(displayObject){ thisObj.unloadImage(displayObject); };
				
				this.currentImageObject.onTransformEndFunction = func;
				
				this.currentImageObject.changeOpacity(0);
			}
			
			this.currentImageObject = newImage;
			
		}
	}
	
	this.unloadImage = function(imageObject){
		
		imageObject.removeFromElement(this.domElement);
		
	}
	
	this.loadFloorplan = function(){
		
		if(this.imageArray != null){
			for(var i in this.imageArray){
				if(this.imageArray[i].type == "floorplan"){
					this.loadImage(i);
					return true;
				}
			}
		}
		
		return false;
	}
	
	this.loadEPC = function(){
		
		if(this.imageArray != null){
			for(var i in this.imageArray){
				if(this.imageArray[i].type == "epc"){
					this.loadImage(i);
					return true;
				}
			}
		}
		
		return false;
	}
	
	// STATUS METHODS
	
	this.addStatusElement = function(){
		
		this.statusElement = this.addElement("p");
		this.statusElement.className = "status";
		//this.statusElement.style.position = "absolute";
		//this.statusElement.style.top = (this.maxImageHeight + 40)+"px";
		//this.statusElement.style.left = "20px";
		
	}
	
	this.setStatus = function(msg){
		this.statusElement.innerHTML = msg;
	}
	
	
	
	// NAVIGATION METHODS
	
	this.addNavigation = function(){
		
		var thisObj = this;
		
		var p = this.addElement("p");
		p.className = "RPWSlideShowNavigation";
		
		//p.style.position = "absolute";
		//p.style.top = (this.maxImageHeight + 40)+"px";
		//p.style.right = "20px";
		
		var button = document.createElement("a");
		button.setAttribute("href","javascript:void(0);");
		button.className = "previous";
		button.title = "Previous";
		button.innerHTML = "<span>Previous</span>";
		button.onclick = function(){ thisObj.gotoPrevious();this.blur();};
		
		p.appendChild(button);
		
		p.appendChild(document.createTextNode(" "));
		
		button = document.createElement("a");
		button.setAttribute("href","javascript:void(0);");
		button.className = "next";
		button.title = "Next";
		button.innerHTML = "<span>Next</span>";
		button.onclick = function(){ thisObj.gotoNext();this.blur();};
		
		p.appendChild(button);
		
		this.domElement.appendChild(p);
	}
	
	this.gotoPrevious = function(){
		
		this.imagePointer --;
		if(this.imagePointer < 0){
			this.imagePointer = this.imageArray.length -1;
		}
		
		this.loadImage(this.imagePointer);
		
	}
	
	this.gotoNext = function(){
		
		this.imagePointer++;
		if(this.imagePointer >= this.imageArray.length){
			this.imagePointer = 0;
		}
		
		this.loadImage(this.imagePointer);
		
	}
	
	
	this.addCloseButton = function(){
		
		button = document.createElement("a");
		button.setAttribute("href","javascript:void(0);");
		button.className = "closeButton";
		button.title = "Close";
		button.innerHTML = "<span>Close</span>";
		
		var thisObj = this;
		button.onclick = function(){ thisObj.remove();};
		//button.style.position = "absolute";
		//button.style.top = "5px";
		//button.style.right = "5px";
		
		this.domElement.appendChild(button);
		
	}
	
	
	this.getOptionButtonsElement = function(){
		
		
		var element = document.createElement("p");
		element.className = "optionButtons";

		this.saveButton = this.getSaveButtonElement();
		
		this.markAsSaved(this.dataObject,this.parentObj.propertyIsSaved(this.dataObject));

		if(this.saveButton != null){
			element.appendChild(this.saveButton);
		}
		
		var button,func;
		var thisObj = this;
		
		// FLOORPLAN BUTTON
		
		if(this.dataObject.floorplans != null){
			
			element.appendChild(document.createTextNode(" "));
		
			button = document.createElement("a");
			button.setAttribute("href","javascript:void(0);");
			button.className = "pOptionButton floorplan";
			
			var title = (this.dataObject.floorplans.length > 1)  ? "Floorplans" : "Floorplan";
			button.innerHTML = "<span>"+title+"</span>";
			button.title = title;
			
			func = function(){thisObj.loadFloorplan();this.blur();}
			
			button.onclick = func;
			
			element.appendChild(button);
		}
		
		// EPC BUTTON
		
		if(this.dataObject.epc != null){
			
			element.appendChild(document.createTextNode(" "));
		
			button = document.createElement("a");
			button.setAttribute("href","javascript:void(0);");
			button.className = "pOptionButton epc";
			button.innerHTML = "<span>EPC</span>";
			button.title = "EPC";
			
			func = function(){thisObj.loadEPC();this.blur();}
			
			button.onclick = func;
			
			element.appendChild(button);
		}
		
		
		
		
		return element;
	
	}

	this.getSaveButtonElement = function(){
		
		var element = document.createElement("a");
		element.setAttribute("href","javascript:void(0);");
		
		var thisObj = this;
		element.onclick = function(e){thisObj.toggleSaved(e);this.blur();};
		
		element.className = "pOptionButton saveToShortlist";
		element.innerHTML = "<span>Save to shortlist</span>";
		element.title = "Save to shortlist";
		
		
		return element;
	
	}
	
	this.toggleSaved = function(e){
		
		if(!this.parentObj.propertyIsSaved(this.dataObject)){
			
			this.parentObj.saveProperty(this.dataObject);
		
		}else{
		
			this.parentObj.removeSavedProperty(this.dataObject);
		
		}
	
	}
	
	this.markAsSaved = function(dataObject,saved){
		
		if(dataObject.db == this.dataObject.db && dataObject.pcode == this.dataObject.pcode){
		
			if(saved){
				this.saveButton.className = "pOptionButton removeFromShortlist";
				this.saveButton.title = "Remove from shortlist";
				this.saveButton.innerHTML = "<span>Remove from shortlist</span>";
			}else{
				this.saveButton.className = "pOptionButton saveToShortlist";
				this.saveButton.title = "Save to shortlist";
				this.saveButton.innerHTML = "<span>Save to shortlist</span>";
			}
		
		}
	}
	



	// init constructor
	
	this.RPWPropertySlideShowObject();
		
}

RPWPropertySlideShowObject.inherits(DisplayObject);


function RPWPropertyImageObject(dataObject){

	DisplayObject.call(this);
	
	this.dataObject = dataObject;
	
	// Constructor
	
	this.RPWPropertyImageObject = function(){
		
		this.createDOMElement("div","RPWPropertyImageObject");
		
	}
	
	this.displayContent = function(maxWidth,maxHeight,crop){
		
		// add image
		
		this.imageElement = this.addElement("img",null,"src",httpRoot+"index.php?action=getthumbnail&filepath="+this.dataObject.filepath+"&width="+maxWidth+"&height="+maxHeight+"&quality=85&crop="+crop);
		if(dataObject.caption != null){
			this.imageElement.title = dataObject.caption;
		}
		
		// get sizes
		var w,h;
		
		if(this.dataObject.width/this.dataObject.height > maxWidth/maxHeight){
			
			w = maxWidth;
			h = this.dataObject.height * maxWidth/this.dataObject.width;
			
		}else{
			
			h = maxHeight;
			w = this.dataObject.width * maxHeight/this.dataObject.height;
		}			
			
		this.setStyle("width", w+"px");
		this.setStyle("height", h+"px");
		
		this.setStyle("left",(20+((maxWidth-w)/2))+"px");
		this.setStyle("top",(30+((maxHeight-h)/2))+"px");
			
		
		if(this.dataObject.description != null){
			
			
		}
		
	}
		
	this.RPWPropertyImageObject();
	
}

RPWPropertyImageObject.inherits(DisplayObject);

function RPWFloorplanViewerObject(dataObject){

	DisplayObject.call(this);

	// create container

	// sub-elements
	this.dataObject = dataObject;

	this.mouseX = null;
	this.mouseY = null;

	this.apertureWidth = null;
	this.apertureHeight = null;

	this.dragAreaObject = null;

	this.RPWFloorplanViewerObject = function(){

		this.createDOMElement("div","RPWFloorplanViewer");
		this.setStyle("overflow","hidden");
		this.setStyle("position","relative");

	}

	this.displayContent = function(w,h){

		this.apertureWidth = w;
		this.apertureHeight = h;

		// add image

		this.imageElement = new DisplayObject();
		this.imageElement.createDOMElement("img");

		//this.imageElement.setDOMAttribute("src",this.dataObject.httppath);
		this.imageElement.setDOMAttribute("src", httpRoot+"index.php?action=getthumbnail&filepath="+this.dataObject.filepath+"&width=1200&height=1200&quality=85&crop=0");

		this.imageElement.setStyle("position","absolute");

		var d = this.getWindowFitDimensions();
		this.imageElement.setStyle("left",d.x+"px");
		this.imageElement.setStyle("top",d.y+"px");
		this.imageElement.setStyle("width",d.width+"px");
		this.imageElement.setStyle("height",d.height+"px");

		this.imageElement.appendToElement(this.domElement);

		this.dragAreaObject = this.addElement("div");
		this.dragAreaObject.style.position = "absolute";
		this.dragAreaObject.style.width = w+"px";
		this.dragAreaObject.style.height = h+"px";
		this.dragAreaObject.style.cursor = "move";
		this.dragAreaObject.style.background = "#FFF";
		this.setOpacity(0,this.dragAreaObject);

		var controlElement = this.getControlElement();
		controlElement.style.position = "absolute";
		this.domElement.appendChild(controlElement);



		this.setStyle("width", w+"px");
		this.setStyle("height", h+"px");

		this.setStyle("left","20px");
		this.setStyle("top","30px");

		this.setStyle("border","1px solid #AAA");

		this.addMouseListener();

	}


	// CONTROLS

	this.getControlElement = function(){

		var element = document.createElement("p");
		element.className = "controlButtons";

		var thisObj = this;

		var zoomInButton = document.createElement("a");
		zoomInButton.href = "javascript:void(0);";
		zoomInButton.onclick = function(){thisObj.zoomIn();this.blur();};
		zoomInButton.className = "zoomIn";
		zoomInButton.title = "Zoom in";
		zoomInButton.innerHTML = "<span>Zoom in</span>";

		element.appendChild(zoomInButton);

		element.appendChild(document.createTextNode(" "));

		var zoomOutButton = document.createElement("a");
		zoomOutButton.href = "javascript:void(0);";
		zoomOutButton.className = "zoomOut";
		zoomOutButton.onclick = function(){thisObj.zoomOut();this.blur();};
		zoomOutButton.title = "Zoom out";
		zoomOutButton.innerHTML = "<span>Zoom out</span>";

		element.appendChild(zoomOutButton);

		element.appendChild(document.createTextNode(" "));

		var fitInWindowButton = document.createElement("a");
		fitInWindowButton.href = "javascript:void(0);";
		fitInWindowButton.className = "fitInWindow";
		fitInWindowButton.onclick = function(){thisObj.fitInWindow();this.blur();};
		fitInWindowButton.title = "Fit in window";
		fitInWindowButton.innerHTML = "<span>Fit in window</span>";

		element.appendChild(fitInWindowButton);
		return element;

	}

	// LISTENERS

	this.addMouseListener = function(){

		var thisObj = this;

		this.dragAreaObject.onmousedown = function(e){ thisObj.addMouseMoveListener(e);return false;};

		this.dragAreaObject.onmouseup = function(e){ thisObj.removeMouseMoveListener(e);};

		this.dragAreaObject.onmouseout = function(e){ thisObj.removeMouseMoveListener(e);};
	}

	this.addMouseMoveListener = function(event){


		event = (!event) ? window.event : event;

		if(event.preventDefault){
			event.preventDefault();
		}

		this.mouseX = event.clientX;
		this.mouseY = event.clientY;

		var thisObj = this;
		this.dragAreaObject.onmousemove = function(e){ thisObj.positionPlan(e);}

		return false;

	}

	this.removeMouseMoveListener = function(event){

		this.dragAreaObject.onmousemove = null;

	}




	// CONTROL METHODS


	this.positionPlan = function(e){

		e = (!e) ? window.event : e;

		this.imageElement.setStyle("left", (parseInt(this.imageElement.getStyle("left")) + e.clientX-this.mouseX)+"px");
		this.imageElement.setStyle("top", (parseInt(this.imageElement.getStyle("top")) + e.clientY-this.mouseY)+"px");
		this.mouseX = e.clientX;
		this.mouseY = e.clientY;

	}

	this.zoomIn = function(){
		this.zoom(4/3);
	}

	this.zoomOut = function(){
		this.zoom(3/4);
	}

	this.zoom = function(ratio){

		// calculate current position;

		var steps = 5;

		var offsetX = parseInt(this.imageElement.getStyle("left"))-(this.apertureWidth/2);
		var offsetY = parseInt(this.imageElement.getStyle("top"))-(this.apertureHeight/2);

		var w = parseInt(this.imageElement.getStyle("width"));
		var h = parseInt(this.imageElement.getStyle("height"));

		w *= ratio;
		h *= ratio;

		offsetX *= ratio;
		offsetY *= ratio;

		offsetX += (this.apertureWidth/2);
		offsetY += (this.apertureHeight/2);


		this.imageElement.changeDimension("left",offsetX,steps);
		this.imageElement.changeDimension("top",offsetY,steps);

		this.imageElement.changeDimension("width",w,steps);
		this.imageElement.changeDimension("height",h,steps);

	}

	this.fitInWindow = function(){

		var d = this.getWindowFitDimensions();
		var steps = 5;

		this.imageElement.changeDimension("left",d.x,steps);
		this.imageElement.changeDimension("top",d.y,steps);

		this.imageElement.changeDimension("width",d.width,steps);
		this.imageElement.changeDimension("height",d.height,steps);

	}

	this.getWindowFitDimensions = function(){

		var newWidth, newHeight, newX, newY;

		if(this.dataObject.width/this.dataObject.height > this.apertureWidth/this.apertureHeight){

			newWidth = this.apertureWidth;
			newHeight = this.dataObject.height*this.apertureWidth/this.dataObject.width;

		}else{
			newHeight = this.apertureHeight;
			newWidth = this.dataObject.width*this.apertureHeight/this.dataObject.height;

		}

		newX = (this.apertureWidth-newWidth)/2;
		newY = (this.apertureHeight-newHeight)/2;

		return { x: newX, y: newY, width: newWidth, height: newHeight };

	}


	// init constructor

	this.RPWFloorplanViewerObject();

}

RPWFloorplanViewerObject.inherits(DisplayObject);




function RPWMortgageCalculatorObject(){

	DisplayObject.call(this);

	this.form = null;

	this.isStandAlone = true;

	this.valueField = null;
	this.depositField = null;
	this.interestRateField = null;
	this.termField = null;
	this.repaymentField = null;
	this.interestOnlyField = null;
	this.showDeposit = true;

	this.propertyValue = null;//150000;
	this.deposit = null;//this.propertyValue*0.15;
	this.interestRate = 5;
	this.term = 25;

	this.introStr = null;
	this.caveatStr = "Guide figures only. For an accurate calculation,<br />please contact your mortage broker.";



	this.RPWMortgageCalculatorObject = function(){

		this.createDOMElement("div","RPWMortgageCalculator");
		this.setStyle("width","260px");

		if (RPWSearchSocket != null) {

			if (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.propertyValue") != null && !isNaN(parseFloat(RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.propertyValue")))) {
				this.propertyValue = RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.propertyValue");
				this.deposit = this.propertyValue*0.15;
			}

			if (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit") != null && !isNaN(parseFloat(RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit")))) {
				//this.deposit = RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit");
			}

			if (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.term") != null && !isNaN(parseFloat(RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.term")))) {
				this.term = RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.term");
			}
			if (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.interestRate") != null && !isNaN(parseFloat(RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.interestRate")))) {
				this.interestRate = RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.interestRate");
			} else if (RPWSearchSocket.getSearchSetting("interestRate") != null) {
				this.interestRate = RPWSearchSocket.getSearchSetting("interestRate");
			}
		}

	}

	this.setValue = function(propertyValue){

		this.propertyValue = propertyValue;
		this.deposit = (RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit") != null && !isNaN(parseFloat(RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit")))) ? RPWSearchSocket.getUserPreference("RPWMortgageCalculatorObject.deposit") : this.propertyValue * 0.15;
	}


	this.displayContent = function(){

		this.clearContents();

		var parentObj = this.getParent();

		this.form = new FormObject("rpwMortgageCalculatorForm");
		this.form.domElement.onsubmit = function(){ return false; };

		this.form.addElement("h3","Mortgage Calculator");

		if (this.introStr != null) {
			var intro = this.form.addElement("p");
			intro.className = "intro";
			intro.innerHTML = this.introStr;
		}

		var thisObj = this;
		var onChange = function(e,element){ thisObj.calculateMortgage(e,element); };

		this.valueField = this.form.addTextField("propertyValue", ((this.showDepositField) ? "Value" : "Mortgage Required"), numberFormat(this.propertyValue));
		this.valueField.setOnChangeListener(onChange);

		if (this.showDepositField) {
			this.depositField = this.form.addTextField("deposit", "Deposit", numberFormat(this.deposit));
			this.depositField.setOnChangeListener(onChange);
		}

		this.interestRateField = this.form.addTextField("interestRate","Interest rate",this.interestRate);
		this.interestRateField.setOnChangeListener(onChange);

		this.termField = this.form.addTextField("term","Term",this.term);
		this.termField.setOnChangeListener(onChange);

		this.repaymentField = this.form.addTextField("repayments","Monthly repayments");

		this.interestOnlyField = this.form.addTextField("interestOnly","Interest Only");

		var parentObj = this.getParent();
		var cancelFunction = function(){parentObj.removeMortgageCalculator();};

		if (this.isStandAlone) {
			var calculateFunction = function(){thisObj.calculateMortgage();};
			this.form.addSubmitLine("Calculate", calculateFunction, cancelFunction, "Close");
		} else {
			var saveFunction = function(){thisObj.showRepayments();};
			this.form.addSubmitLine("Show repayments", saveFunction, cancelFunction, "Close");
		}

		if (this.caveatStr != null) {
			var caveat = this.form.addElement("p");
			caveat.className = "caveat";
			caveat.innerHTML = this.caveatStr;
		}

		this.form.appendToElement(this.domElement);

		this.setPosition();

		this.calculateMortgage();

	}

	this.setPosition = function(){

		this.setStyle("position","absolute");

		// get image width and height

		var pageSizes = this.getPageSizeObject();

		var w = this.getWidth();
		var h = this.getHeight();

		var yScroll = this.getYScroll();

		var top = Math.max(0,yScroll + ((pageSizes.windowHeight - h) / 2));

		this.setStyle("top",top+"px");
		this.setStyle("left", Math.max(0,(pageSizes.pageWidth - w) / 2) + "px");

	}

	this.showRepayments = function(){

		if(parentObj = this.getParent()){

			var regex = /[^\d\.]/g;
			RPWSearchSocket.saveUserPreference("RPWMortgageCalculatorObject.deposit", String(this.depositField.getValue()).replace(regex,""));

			parentObj.setAttribute("RPWPropertyListObject.showMortgageRepayments",true);
			parentObj.showRepayments();
			parentObj.removeMortgageCalculator();

		}

	}


	this.calculateMortgage = function(e,element){

		var regex = /[^\d\.]/g;

		if (element != null) {
			var savedValue = String(element.getValue()).replace(regex,"");
			savedValue = parseFloat(savedValue);
			if (!isNaN(savedValue)) {
				RPWSearchSocket.saveUserPreference("RPWMortgageCalculatorObject." + element.fieldName, savedValue);
			}
		}

		// error checking
		var propertyValue, deposit, term, interestRate;

		var errorFields = new Array();
		var errors = new Array();

		if(this.valueField.getValue() == null){
			errorFields.push(this.valueField);
			errors.push("Please enter a value for the property value.");
		}else{
			propertyValue = String(this.valueField.getValue()).replace(regex,"");
			propertyValue = parseFloat(propertyValue);
			if(isNaN(propertyValue)){
				errorFields.push(this.valueField);
				errors.push("Please enter a valid figure for the property value.");
			}
		}

		if (this.showDepositField) {
			if (this.depositField.getValue() == null) {
				errorFields.push(this.depositField);
				errors.push("Please enter a value for the deposit.");
			} else {
				deposit = String(this.depositField.getValue()).replace(regex, "");
				deposit = parseFloat(deposit);
				if (isNaN(deposit)) {
					errorFields.push(this.depositField);
					errors.push("Please enter a valid figure for the deposit.");
				}
			}
		}else{
			deposit = 0;
		}

		if(this.interestRateField.getValue() == null){
			errorFields.push(this.interestRateField);
			errors.push("Please enter a value for the interest rate.");
		}else{
			interestRate = String(this.interestRateField.getValue()).replace(regex,"");
			interestRate = parseFloat(interestRate);
			if(isNaN(interestRate)){
				errorFields.push(this.interestRateField);
				errors.push("Please enter a valid figure for the interest rate.");
			}
		}

		if(this.termField.getValue() == null){
			errorFields.push(this.termField);
			errors.push("Please enter a value for the term.");
		}else{
			term = String(this.termField.getValue()).replace(regex,"");
			term = parseFloat(term);
			if(isNaN(term)){
				errorFields.push(this.termField);
				errors.push("Please enter a valid figure for the term.");
			}
		}

		if(errors.length > 0){

			for(var i=0;i< errorFields.length;i++){
				errorFields[i].setClass("textbox error");
			}

			window.alert(errors.join("\n"));

			errorFields[0].focus();

			return;
		}

		// caclulate mortgage
		interestRate = interestRate / 100;
		var amount = propertyValue-deposit;

		var p = ((amount*interestRate)/12) * (1/(1-(Math.pow(1/(1+interestRate),term))));
		var i = ((amount*interestRate)/12);

		this.repaymentField.setValue(numberFormat(p,2));
		this.interestOnlyField.setValue(numberFormat(i,2));


	}

	this.setCaveat = function(str){
		this.caveatStr = str;
	}

	this.setIntro = function(str){
		this.introStr = str;
	}

	this.RPWMortgageCalculatorObject();

}

RPWMortgageCalculatorObject.inherits(DisplayObject);
function RPWViewingRequestFormObject(){

	DisplayObject.call(this);

	this.form = null;

	this.titleStr = "Book a Viewing";
	this.address = null;
	this.introStr = null;
	this.formFields = "Name*,Telephone*,E-mail*,Address";
	this.recipient = null;
	this.pcode = null;
	this.rps = null;
	this.action = null;

	this.introStr = null;


	this.RPWViewingRequestFormObject = function(){

		this.createDOMElement("div", "RPWViewingRequestForm");
		this.setStyle("width", "330px");

	}


	this.displayContent = function(){

		this.clearContents();

		var parentObj = this.getParent();

		this.form = new FormObject("rpwViewingRequestForm");
		this.form.domElement.onsubmit = function(){ return false; };

		this.form.addElement("h3",this.titleStr);

		if(this.address){
			this.form.addElement("h4",this.address);
		}

		// INTRO

		if (this.introStr != null) {
			var intro = this.form.addElement("p");
			intro.className = "intro";
			intro.innerHTML = this.introStr;
		}

		// HIDDEN FIELDS

		this.form.addHiddenField("_pcode",this.pcode);
		this.form.addHiddenField("_rps",this.rps);
		this.form.addHiddenField("Property",this.address);

		// FIELDS

		var formFields = this.formFields.split(",");
		var field;
		var required;
		var requiredRegex = /\*$/;

		for(var i in formFields){

			field = formFields[i].replace(/^\s\s*/, '').replace(/\s\s*$/, '');

			if(field.match(requiredRegex)){
				required = true;
				field = field.replace(requiredRegex,"");
			}else{
				required = false;
			}

			if(field.toLowerCase() == "address"){
				this.form.addMemoField(field,field,null,null,required);
			}else{
				this.form.addTextField(field,field,null,null,required);
			}

		}

		// SUBMIT

		var thisObj = this;

		var cancelFunction = function(){
			thisObj.cancel();
		}

		var submitFunction = function(){
			thisObj.submit();
		}

		this.form.addSubmitLine("Submit", submitFunction, cancelFunction, "Cancel");

		this.form.appendToElement(this.domElement);

		this.setPosition();

	}

	this.submit = function(){
		if(this.form.validate()){

			var data = this.form.getData();

			if(RPWSearchSocket != null){

				var thisObj = this;
				var callbackFunc = function(data){
					thisObj.onRequestSend(data);
				}

				RPWSearchSocket.makeCall("bookViewing", this.action, data, callbackFunc);

			}

		}
	}

	this.onRequestSend = function(data){

		this.clearContents();

		this.addElement("p",data.result);
		var closePara = this.addElement("p");

		var a = document.createElement("a");
		a.setAttribute("href","#");

		var thisObj = this;

		a.onclick = function(){
			thisObj.cancel();
		}

		a.innerHTML = "Close";
		closePara.appendChild(a);

	}

	this.cancel = function(){

		var parentObj = this.getParent();
		if (parentObj != null && typeof parentObj.removeViewingRequestForm != "undefined") {
			parentObj.removeViewingRequestForm();
		}else if(this.onRemoveFunction != null){
			this.onRemoveFunction();
		}else if(this.domElement.parent != null){
			this.domElement.parent.removeChild(this.domElement);
		}

	}

	this.setPosition = function(){

		this.setStyle("position","absolute");

		// get image width and height

		var pageSizes = this.getPageSizeObject();

		var w = this.getWidth();
		var h = this.getHeight();

		var yScroll = this.getYScroll();

		var top = Math.max(0,yScroll + ((pageSizes.windowHeight - h) / 2));

		this.setStyle("top",top+"px");
		this.setStyle("left", Math.max(0,(pageSizes.pageWidth - w) / 2) + "px");

	}



	this.RPWViewingRequestFormObject();

}

RPWViewingRequestFormObject.inherits(DisplayObject);function RPWGoogleMapObject(){

	DisplayObject.call(this);



	this.gMapObj = null;
	this.markerManager = null;
	this.schoolMarkerManager = null;
	this.officeMarkerManager = null;
	this.resultsDisplayed = false;

	this.googleMapDOMElement = null;

	this.dataObject = null;
	this.schoolData = null;

	this.showOffices = true;
	this.showPrimarySchools = false;
	this.showSecondarySchools = false;
	this.showStationInfo = false;

	if(navigator.appName.toLowerCase().indexOf("microsoft") == -1){
		this.schoolMinZoom = 11;
	}else{
		this.schoolMinZoom = 12;
	}

	this.stationMinZoom = this.schoolMinZoom;

	this.controlElement = null;
	this.primarySchoolControl = null;
	this.secondarySchoolControl = null;
	this.stationInfoControl = null;

	this.primarySchoolKeyIcon = null;
	this.secondarySchoolKeyIcon = null;
	this.stationInfoKeyIcon = null;


	this.north = null;
	this.south = null;
	this.east = null;
	this.west = null;

	this.searchMode = false;

	this.batchTotal = 200;


	this.propertyListArray = new Array();
	this.markerDataObject = null;

	this.propertyObject = null;// object to store displayed property
	this.displayMode = "search";


	this.RPWGoogleMapObject = function(){

		this.createDOMElement("div","RPWGoogleMap");
		this.setStyle("position","relative");

		// define icons
		this.propertyIcon = new GIcon();
		this.propertyIcon.image = httpRoot+"images/gmap-house.png";
		this.propertyIcon.shadow = httpRoot+"images/gmap-house-shadow.png";
		this.propertyIcon.iconSize = new GSize(29, 25);
		this.propertyIcon.shadowSize = new GSize(29, 25);
		this.propertyIcon.iconAnchor = new GPoint(13, 20);
		this.propertyIcon.infoWindowAnchor = new GPoint(10, 17);

		this.propertiesIcon = new GIcon();
		this.propertiesIcon.image = httpRoot+"images/gmap-2house.png";
		this.propertiesIcon.shadow = httpRoot+"images/gmap-2house-shadow.png";
		this.propertiesIcon.iconSize = new GSize(36, 26);
		this.propertiesIcon.shadowSize = new GSize(36, 26);
		this.propertiesIcon.iconAnchor = new GPoint(14, 15);
		this.propertiesIcon.infoWindowAnchor = new GPoint(17, 10);

		this.officeIcon = new GIcon();
		this.officeIcon.image = httpRoot+"images/gmap-office.png";
		this.officeIcon.shadow = httpRoot+"images/gmap-house-shadow.png";
		this.officeIcon.iconSize = new GSize(29, 25);
		this.officeIcon.shadowSize = new GSize(29, 25);
		this.officeIcon.iconAnchor = new GPoint(13, 20);
		this.officeIcon.infoWindowAnchor = new GPoint(10, 17);

		this.primarySchoolIcon = new GIcon();
		this.primarySchoolIcon.image = httpRoot+"images/live_list/map/primary-school-icon.png";
		this.primarySchoolIcon.shadow = httpRoot+"images/live_list/map/school-icon-shadow.png";
		this.primarySchoolIcon.iconSize = new GSize(18,18);
		this.primarySchoolIcon.shadowSize = new GSize(20, 20);
		this.primarySchoolIcon.iconAnchor = new GPoint(9,9);
		this.primarySchoolIcon.infoWindowAnchor = new GPoint(9,9);

		this.secondarySchoolIcon = new GIcon();
		this.secondarySchoolIcon.image = httpRoot+"images/live_list/map/secondary-school-icon.png";
		this.secondarySchoolIcon.shadow = httpRoot+"images/live_list/map/school-icon-shadow.png";
		this.secondarySchoolIcon.iconSize = new GSize(18,18);
		this.secondarySchoolIcon.shadowSize = new GSize(20, 20);
		this.secondarySchoolIcon.iconAnchor = new GPoint(9,9);
		this.secondarySchoolIcon.infoWindowAnchor = new GPoint(9,9);

		this.independentSchoolIcon = new GIcon();
		this.independentSchoolIcon.image = httpRoot+"images/live_list/map/independent-school-icon.png";
		this.independentSchoolIcon.shadow = httpRoot+"images/live_list/map/school-icon-shadow.png";
		this.independentSchoolIcon.iconSize = new GSize(18,18);
		this.independentSchoolIcon.iconAnchor = new GPoint(9,9);
		this.independentSchoolIcon.infoWindowAnchor = new GPoint(9,9);

		this.stationInfoIcon = new GIcon();
		this.stationInfoIcon.image = httpRoot+"images/live_list/map/station-info-icon.png";
		this.stationInfoIcon.shadow = httpRoot+"images/live_list/map/station-info-icon-shadow.png";
		this.stationInfoIcon.iconSize = new GSize(18,18);
		this.stationInfoIcon.iconAnchor = new GPoint(9,9);
		this.stationInfoIcon.infoWindowAnchor = new GPoint(9,9);
	}

	this.zoomTo = function(lat,lng,zoomLevel){
		if(this.gMapObj != null){
			var centre = new GLatLng(lat,lng);
			this.gMapObj.panTo(centre);
			if(zoomLevel){
				this.gMapObj.setZoom(zoomLevel);
			}else{
				this.gMapObj.zoomIn();
			}
		}
	}


	this.reset = function(){
		this.dataObject = null;
		this.markerDataObject = null;
		this.clearMap();
	}


	this.clearMap = function(){

		if (this.gMapObj != null) {
			this.gMapObj.clearOverlays();
		}
		this.propertyListArray = new Array();
		this.resultsDisplayed = false;
		this.schoolData = null;
		if(this.markerManager != null){
			this.markerManager.clearMarkers();
			this.markerManager.refresh();
		}

		if(this.schoolMarkerManager != null){
			this.schoolMarkerManager.clearMarkers();
			this.schoolMarkerManager.refresh();
		}
	}


	this.getMarkerManager = function(){

		if(this.markerManager == null){
			this.markerManager = new MarkerManager(this.gMapObj);
		}

		return this.markerManager;
	}

	this.onZoomEnd = function(){

		if(!this.searchMode) {
			this.doSearch();
		}

	}

	this.onMoveEnd = function(){

		if(!this.searchMode) {
			this.doSearch();
		}

	}

	this.loadSecondaryContent = function(){

		if(this.gMapObj.getZoom() >= this.schoolMinZoom){
			this.primarySchoolControl.enable();
			this.secondarySchoolControl.enable();
			setOpacity(this.primarySchoolKeyIcon,100);
			setOpacity(this.secondarySchoolKeyIcon,100);
			this.primarySchoolLabel.className = "";
			this.secondarySchoolLabel.className = "";
		}else{
			this.primarySchoolControl.disable();
			this.secondarySchoolControl.disable();
			setOpacity(this.primarySchoolKeyIcon,50);
			setOpacity(this.secondarySchoolKeyIcon,50);
			this.primarySchoolLabel.className = "disabled";
			this.secondarySchoolLabel.className = "disabled";
		}

		this.loadOffices();

		if((this.showPrimarySchools || this.showSecondarySchools) && this.gMapObj.getZoom() >= this.schoolMinZoom){
			this.loadSchools();
		}else if(this.gMapObj.getZoom() < this.schoolMinZoom){
			this.clearSchools();
		}

		if(this.gMapObj.getZoom() >= this.stationMinZoom){
			this.stationInfoControl.enable();
			setOpacity(this.stationInfoKeyIcon,100);
			this.stationInfoLabel.className = "";
		}else{
			this.stationInfoControl.disable();
			setOpacity(this.stationInfoKeyIcon,50);
			this.stationInfoLabel.className = "disabled";
		}

		if(this.showStationInfo && this.gMapObj.getZoom() >= this.stationMinZoom){
			this.loadStations();
		}else if(this.gMapObj.getZoom() < this.schoolMinZoom){
			this.clearStations();
		}
	}

	this.displayContent = function(){

		// load preferences

		if(this.getAttribute("RPWGoogleMapObject.showOffices") != null){
			this.showOffices =  Boolean(Number(this.getAttribute("RPWGoogleMapObject.showOffices")));
		}

		if(this.getAttribute("RPWGoogleMapObject.showPrimarySchools") != null){
			this.showPrimarySchools =  Boolean(Number(this.getAttribute("RPWGoogleMapObject.showPrimarySchools")));
		}

		if(this.getAttribute("RPWGoogleMapObject.showSecondarySchools") != null){
			this.showSecondarySchools =  Boolean(Number(this.getAttribute("RPWGoogleMapObject.showSecondarySchools")));
		}

		if(this.getAttribute("RPWGoogleMapObject.showStationInfo") != null){
			this.showStationInfo =  Boolean(Number(this.getAttribute("RPWGoogleMapObject.showStationInfo")));
		}


		this.addControlStrip();

		this.googleMapDOMElement = this.addElement("div");
		this.googleMapDOMElement.className = "gMapDOMElement";

	}

	this.initGMapObj = function(){

		if (GBrowserIsCompatible()) {

			this.gMapObj = new GMap2(this.googleMapDOMElement);
			this.gMapObj.addControl(new GLargeMapControl3D());
			if(this.getAttribute("RPWGoogleMapObject.mapTypeControl") == "buttons"){
				this.gMapObj.addControl(new GHierarchicalMapTypeControl());
			}else{
				this.gMapObj.addControl(new GMenuMapTypeControl());
			}
			//this.gMapObj.addOverlay(new GStreetviewOverlay());
			//this.gMapObj.addControl(new GStreetviewClient());

			var thisObj = this;
			GEvent.addListener(this.gMapObj, "zoomend", function(){ thisObj.onZoomEnd(); });
			GEvent.addListener(this.gMapObj, "moveend", function(){ thisObj.onMoveEnd(); });

		}else{

			window.alert("Sorry, your browser is not compatible with Google maps");

		}
	}

	this.resizeTo = function(w,h){

		if (!isNaN(parseInt(this.getStyle("padding-left")))) {
			w -= parseInt(this.getStyle("padding-left"));
		}
		if (!isNaN(parseInt(this.getStyle("padding-right")))) {
			w -= parseInt(this.getStyle("padding-right"));
		}

		if (!isNaN(parseInt(this.getStyle("border-width", this.googleMapDOMElement)))) {
			w -= parseInt(this.getStyle("border-width", this.googleMapDOMElement));
		}

		this.googleMapDOMElement.style.width = w+"px";

		if (!isNaN(parseInt(this.getStyle("padding-top")))) {
			h -= parseInt(this.getStyle("padding-top"));
		}
		if (!isNaN(parseInt(this.getStyle("padding-bottom")))) {
			h -= parseInt(this.getStyle("padding-bottom"));
		}

		this.setStyle("height",h+"px");

		h -= this.controlElement.getHeight();

		this.googleMapDOMElement.style.height = h+"px";

		if(this.gMapObj != null){
			this.gMapObj.checkResize();
		}

	}


	this.addControlStrip = function(){

		this.controlElement = this.addDisplayObject("div");
		this.controlElement.domElement.className = "control";

		var thisObj = this;

		var propertyKey = this.controlElement.addDisplayObject("span");
		propertyKey.setClass("propertyKey");

		var icon = propertyKey.addElement("img");
		icon.setAttribute("src",httpRoot+"images/live_list/map/house-icon.gif");

		propertyKey.addText("Property ");

		icon = propertyKey.addElement("img");
		icon.setAttribute("src",httpRoot+"images/live_list/map/houses-icon.gif");

		propertyKey.addText("2+ properties ");



		this.controlElement.addText("Show: ");

		// OFFICES

		icon = this.controlElement.addElement("img");
		icon.setAttribute("src",httpRoot+"images/live_list/map/office-icon.gif");

		this.controlElement.addText("Offices ");

		var input = new CheckBoxElement("officeStatus","Offices",this.showOffices);

		var onChange = function(){thisObj.toggleOffices(this);};

		input.setOnChangeListener(onChange);

		input.displayContent();

		this.controlElement.appendChild(input.domElement);


		// PRIMARY SCHOOLS

		this.primarySchoolKeyIcon = this.controlElement.addElement("img");
		this.primarySchoolKeyIcon.setAttribute("src",httpRoot+"images/live_list/map/primary-school-icon.gif");

		this.primarySchoolLabel = this.controlElement.addElement("span","Primary Schools");

		this.primarySchoolControl = new CheckBoxElement("primarySchoolStatus","Primary Schools",this.showPrimarySchools);
		this.primarySchoolControl.setParent(this);

		onChange = function(){thisObj.togglePrimarySchools(this);};

		this.primarySchoolControl.setOnChangeListener(onChange);

		this.primarySchoolControl.displayContent();

		this.controlElement.appendChild(this.primarySchoolControl.domElement);


		// SECONDARY SCHOOLS

		this.secondarySchoolKeyIcon = this.controlElement.addElement("img");
		this.secondarySchoolKeyIcon.setAttribute("src",httpRoot+"images/live_list/map/secondary-school-icon.gif");

		this.secondarySchoolLabel = this.controlElement.addElement("span","Secondary Schools");

		this.secondarySchoolControl = new CheckBoxElement("secondarySchoolStatus","Secondary Schools",this.showSecondarySchools);

		onChange = function(){thisObj.toggleSecondarySchools(this);};

		this.secondarySchoolControl.setOnChangeListener(onChange);

		this.secondarySchoolControl.setStyle("display","inline");

		this.secondarySchoolControl.displayContent();

		this.controlElement.appendChild(this.secondarySchoolControl.domElement);


		// STATIONS

		this.stationInfoKeyIcon = this.controlElement.addElement("img");
		this.stationInfoKeyIcon.setAttribute("src",httpRoot+"images/live_list/map/station-info-icon.gif");

		this.stationInfoLabel = this.controlElement.addElement("span","Station info");

		this.stationInfoControl = new CheckBoxElement("stationInfoStatus","Station info",this.showStationInfo);

		onChange = function(){thisObj.toggleStationInfo(this);};

		this.stationInfoControl.setOnChangeListener(onChange);

		this.stationInfoControl.displayContent();

		this.controlElement.appendChild(this.stationInfoControl.domElement);

	}

	this.displayStatusMessage = function(msg){

		this.clearStatusMessage();

		this.statusMessageElement = this.addDisplayObject("div");
		this.statusMessageElement.addText(msg);
		this.statusMessageElement.setClass("statusMessage");
		this.statusMessageElement.setStyle("top",this.controlElement.getHeight()+"px");
		this.statusMessageElement.setStyle("position","absolute");
		this.statusMessageElement.setStyle("width","300px");
		this.statusMessageElement.setStyle("zIndex","800");
		this.statusMessageElement.setStyle("left",(this.controlElement.getWidth()/2 - 150) + "px");
		this.statusMessageElement.setOpacity(75);
		this.statusMessageElement.appendToElement(this.domElement);
	}

	this.clearStatusMessage = function(){

		if(this.statusMessageElement != null){
			this.statusMessageElement.removeFromElement(this.domElement);
			this.statusMessageElement = null;
		}

	}



	// PROPERTIES

	this.loadResults = function(){

		if(this.gMapObj == null){
			this.initGMapObj();
		}

		this.clearStatusMessage();

		if(RPWSearchSocket != null){

			this.parentObj.showLoadingGraphic();

			var thisObj = this;

			var onLoad = function(data){ thisObj.displayResults(data) };

			RPWSearchSocket.getResultSet(0,this.batchTotal,onLoad);

		}
	}

	this.processPropertyData = function(data){

		// create data set:
		// zoomSet[i]points[postcode stub]properties[j] = dataObj

		// assemble properties into array of points
		var zoomSet = new Array();

		var south = null;
		var north = null;
		var west = null;
		var east = null;

		var propertyObj;

		var pattern;

		var match;

		var patternArray = [ /^[A-Za-z]{1,2}/i, /^[A-Za-z]{1,2}[\d]{1,2}[A-Za-z]?/i, /^[A-Za-z]{1,2}[\d]{1,2}[A-Za-z]? [0-9]/i];// postcode stub patterns
		var minZoomArray = [6,8,12];
		var maxZoomArray = [7,11,13];

		for(var i=0;i<data.length;i++){

			propertyObj = data[i];

			if(propertyObj.latitude != null && propertyObj.longitude != null){// we have goecode info - add to set

				if(north == null){
					// set min/max lat and lng
					south = propertyObj.latitude;
					north = propertyObj.latitude;
					west = propertyObj.longitude;
					east = propertyObj.longitude;

				}else{

					// set min/max lat and lng
					south = Math.min(south, propertyObj.latitude);
					north = Math.max(north, propertyObj.latitude);
					west = Math.min(west, propertyObj.longitude);
					east = Math.max(east, propertyObj.longitude);

				}

				for(var j=0;j<patternArray.length;j++){// loop through various stages of postcode

					match = String(propertyObj.postcode).match(patternArray[j]);

					if(match != null){

						if(zoomSet[j] == null){
							zoomSet[j] = {minZoom:minZoomArray[j], maxZoom:maxZoomArray[j]};
							zoomSet[j]["points"] = new Object();
						}

						if(zoomSet[j]["points"][match] == null){
							zoomSet[j]["points"][match] = {latitude: Number(propertyObj.latitude), longitude: Number(propertyObj.longitude)};// use current property for initial values
							zoomSet[j]["points"][match]["properties"] = new Array();
						}else{
							// add lat and lng (to be divided by total later);
							zoomSet[j]["points"][match].latitude += Number(propertyObj.latitude);
							zoomSet[j]["points"][match].longitude += Number(propertyObj.longitude);
						}

						zoomSet[j]["points"][match]["properties"].push(data[i]);


					}

				}



				// add final point for property
				if(zoomSet[j] == null){
					zoomSet[j] = {minZoom:14};
					zoomSet[j]["points"] = new Object();
				}

				if(zoomSet[j]["points"][propertyObj.postcode] == null){
					zoomSet[j]["points"][propertyObj.postcode] = {latitude: propertyObj.latitude, longitude: propertyObj.longitude};// use current property for initial values
					zoomSet[j]["points"][propertyObj.postcode]["properties"] = new Array();
				}

				zoomSet[j]["points"][propertyObj.postcode]["properties"].push(data[i]);

			}

		}

		// loop throug marker points to set lat/lng centres by dividing them by property totals

		for(var i=0;i<patternArray.length;i++){

			if(zoomSet[i] != null && zoomSet[i]["points"] != null){

				for(j in zoomSet[i]["points"]){

					zoomSet[i]["points"][j].latitude = zoomSet[i]["points"][j].latitude/zoomSet[i]["points"][j].properties.length;
					zoomSet[i]["points"][j].longitude = zoomSet[i]["points"][j].longitude/zoomSet[i]["points"][j].properties.length;

				}

			}

		}

		this.north = north;
		this.south = south;
		this.east = east;
		this.west = west;
		this.markerDataObject = (zoomSet.length > 0) ? zoomSet : null;

		if(!this.searchMode && this.north != null){// move map

			this.searchMode = true;

			var lat = this.south + (this.north-this.south)/2;
			var lng = this.west + (this.east-this.west)/2;

			var center = new GLatLng(lat,lng);
			this.gMapObj.setCenter(center);

			var boundingBox = new GLatLngBounds(new GLatLng(this.south,this.west), new GLatLng(this.north,this.east));
			var zoom = this.gMapObj.getBoundsZoomLevel(boundingBox);

			this.gMapObj.setZoom(zoom);

		}

	}


	this.displayResults = function(results){

		if(results.error != null){
			this.parentObj.hideLoadingGraphic();
			alert(results.error);
			return;
		}

		if(results != null){
			this.dataObject = results;
			this.displayMode = "search";
			if (this.dataObject.properties != null) {
				this.processPropertyData(this.dataObject.properties);
			}

		}


		if(this.gMapObj == null){

			this.parentObj.hideLoadingGraphic();
			alert("Error: google map not present");
			return;

		}


		this.clearMap();

		if(this.displayMode == "property"){
			this.displayProperty();
		}else{
			this.displayProperties();
			if(this.dataObject.resultTotal > this.batchTotal){
				this.displayStatusMessage("Displaying " + this.batchTotal + " of "+ this.dataObject.resultTotal+" properties. To view a full selection, zoom in or narrow your search criteria.");
			}
		}

		this.loadSchools();
		this.loadOffices();
		this.loadStations();

		this.searchMode = false;

		this.parentObj.hideLoadingGraphic();

	}

	this.displayProperties = function(){


		this.propertyListArray = new Array();


		if(this.dataObject.properties != null){

			var markers = this.markerDataObject;

			if(markers != null){

				var markerManager = this.getMarkerManager();

				var batch;

				for(var i=0;i<markers.length;i++){


					if(markers[i].points != null){

						batch = new Array();

						for(var j in markers[i].points){

							batch.push(this.createPropertyMarker(markers[i].points[j],markers[i].maxZoom));

						}


						markerManager.addMarkers(batch, markers[i].minZoom, markers[i].maxZoom);

					}


				}

				markerManager.refresh();

				this.gMapObj.savePosition();


			}else{
				alert("Sorry, no map data was found for the properties in this search.");

			}

			this.resultsDisplayed = true;

		}

	}

	this.createPropertyMarker = function(dataObj,zoomLimit){
		// assemble node for info window

		var infoNode = document.createElement("div");
		infoNode.className = "gMapInfoWindow";

		var offices = new Array();


		if(dataObj.properties != null){

			if(dataObj.properties.length > 50){// too many properties to show in one window - show total and zoom

				var thisObj = this;
				var zoomFunc = function(){thisObj.zoomTo(dataObj.latitude,dataObj.longitude,((zoomLimit) ? Number(zoomLimit)+1 : null))};

				var totalNode = document.createElement("p");

				var element = document.createElement("strong");
				element.innerHTML = dataObj.properties.length+" properties";
				totalNode.appendChild(element);

				totalNode.appendChild(document.createElement("br"));
				totalNode.appendChild(document.createElement("br"));

				var zoomNode = document.createElement("a");
				zoomNode.className = "zoom detail";
				zoomNode.setAttribute("href","javascript:void(0);");
				zoomNode.onclick = zoomFunc;
				zoomNode.innerHTML = "Zoom in";

				totalNode.appendChild(zoomNode);

				infoNode.appendChild(totalNode);

			}else{

				var propertyInfoObject;

				var hideImage = false;//(dataObj.properties.length > 8);

				for(var i in dataObj.properties){

					propertyInfoObject = new RPWGoogleMapPropertyInfoObject(dataObj.properties[i]);

					propertyInfoObject.setParent(this);

					propertyInfoObject.displayContent(hideImage);

					infoNode.appendChild(propertyInfoObject.getDOMElement());

					this.propertyListArray.push(propertyInfoObject);


				}

				if (dataObj.properties.length > 2) {
					infoNode.style.maxHeight = "320px";
					infoNode.style.overflowY = "auto";
				}

				infoNode.style.width = "420px";
			}
		}

		var point = new GLatLng(dataObj.latitude,dataObj.longitude);
		var icon;
		if(dataObj.properties.length > 1){
			icon =  this.propertiesIcon;
		}else if(offices.length > 0){
			icon = this.officeIcon;
		}else{
			icon = this.propertyIcon;
		}

		return this.createGMapMarker(point,infoNode,icon);
	}



	this.createGMapMarker = function(point,node,icon){
		var marker = new GMarker(point, icon);
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindow(node );
		});
		return marker;
	}


	this.markItemAsSaved = function(dataObject,saved){

		for(var i in this.propertyListArray){

			if(this.propertyListArray[i].dataObject.db == dataObject.db && this.propertyListArray[i].dataObject.pcode == dataObject.pcode){
				this.propertyListArray[i].markAsSaved(saved);
			}

		}

	}

	this.showProperty = function(dataObj){

		if(this.gMapObj == null){
			this.initGMapObj();
		}

		this.propertyObject = dataObj;

		this.displayMode = "property";

		this.clearMap();

		this.displayProperty();

		this.loadSchools();

		this.loadStations();

		this.displayOffices();
	}

	this.displayProperty = function(){

		if(this.propertyObject != null){

			var point = new GLatLng(this.propertyObject.latitude,this.propertyObject.longitude);
			var icon = this.propertyIcon;

			var infoNode = document.createElement("div");
			infoNode.className = "gMapInfoWindow";

			var propertyInfoObject = new RPWGoogleMapPropertyInfoObject(this.propertyObject);

			propertyInfoObject.setParent(this);

			propertyInfoObject.displayContent(false);

			infoNode.appendChild(propertyInfoObject.getDOMElement());

			this.propertyListArray.push(propertyInfoObject);

			var marker = this.createGMapMarker(point,infoNode,icon);

			this.searchMode = true;

			this.gMapObj.addOverlay(marker);
			this.gMapObj.setCenter(point);
			this.gMapObj.setZoom(15);
			this.gMapObj.savePosition();

			this.searchMode = false;

			marker.openInfoWindow(infoNode);

		}

	}


	// SCHOOLS

	this.getSchoolMarkerManager = function(){

		if(this.schoolMarkerManager == null){
			this.schoolMarkerManager = new MarkerManager(this.gMapObj);
		}

		return this.schoolMarkerManager;
	}

	this.clearSchools = function(){
		if(this.schoolMarkerManager != null){
			this.schoolMarkerManager.clearMarkers();
			this.schoolMarkerManager.refresh();
		}
		this.schoolData = null;
	}

	this.togglePrimarySchools = function(input){

		this.parentObj.savePreference("RPWGoogleMapObject.showPrimarySchools",Number(input.getValue()));

		this.showPrimarySchools = input.getValue();
		if(this.schoolMarkerManager != null){
			this.schoolMarkerManager.clearMarkers();
			this.schoolMarkerManager.refresh();
		}
		if(input.getValue() && this.schoolData == null){
			this.loadSchools();
		}else{
			this.displaySchools();
		}

	}

	this.toggleSecondarySchools = function(input){

		this.parentObj.savePreference("RPWGoogleMapObject.showSecondarySchools",Number(input.getValue()));

		this.showSecondarySchools = input.getValue();
		if(this.schoolMarkerManager != null){
			this.schoolMarkerManager.clearMarkers();
			this.schoolMarkerManager.refresh();
		}
		if(input.getValue() && this.schoolData == null){
			this.loadSchools();
		}else{
			this.displaySchools();
		}

	}

	this.doSearch = function(){

		var bounds = this.gMapObj.getBounds();

		var sw = bounds.getSouthWest();
		var ne = bounds.getNorthEast();

		RPWSearchSocket.setSearchSetting("south", Math.min(sw.lat(),ne.lat()));
		RPWSearchSocket.setSearchSetting("north", Math.max(sw.lat(),ne.lat()));
		RPWSearchSocket.setSearchSetting("west", Math.min(sw.lng(),ne.lng()));
		RPWSearchSocket.setSearchSetting("east", Math.max(sw.lng(),ne.lng()));

		RPWSearchSocket.setSearchSetting("webarea", null);
		RPWSearchSocket.setSearchSetting("ocode", null);
		RPWSearchSocket.clearAreas();


		//var thisObj = this;

		//var onLoadFunc = function(data){ thisObj.displaySchools(data);};

		this.searchMode = true;

		RPWSearchSocket.doSearch();
	}


	this.loadSchools = function(){

		if((this.showPrimarySchools || this.showSecondarySchools)  && this.gMapObj.getZoom() >= this.schoolMinZoom){

			var bounds = this.gMapObj.getBounds();

			var sw = bounds.getSouthWest();
			var ne = bounds.getNorthEast();

			var lat1 = Math.min(sw.lat(),ne.lat());
			var lat2 = Math.max(sw.lat(),ne.lat());
			var lng1 = Math.min(sw.lng(),ne.lng());
			var lng2 = Math.max(sw.lng(),ne.lng());


			var thisObj = this;

			var onLoadFunc = function(data){ thisObj.displaySchools(data);};

			RPWSearchSocket.getSchools(lat1,lat2,lng1,lng2,onLoadFunc);

		}

	}


	this.displaySchools = function(data){

		if(data != null){
			if(this.dataObject == null){
				this.dataObject = new Object();
			}
			this.schoolData = data.schools;
		}

		//alert("Data: "+this.schoolData+", Length: "+this.schoolData.length+", Primary schools: "+this.showPrimarySchools+", Secondary schools: "+this.showSecondarySchools);


		if(this.schoolData != null && this.schoolData.length > 0 && (this.showPrimarySchools || this.showSecondarySchools)){

			if(this.schoolMarkerManager != null){
				this.schoolMarkerManager.clearMarkers();
				this.schoolMarkerManager.refresh();
			}
			var schoolNode;
			var point;
			var icon;
			var marker;

			var markerManager = this.getSchoolMarkerManager();

			for(var i in this.schoolData){

				if(Number(this.schoolData[i].STAT_HIGH_AGE) > 11){
					if(!this.showSecondarySchools){
						continue;
					}
					icon = this.secondarySchoolIcon;
				}else{
					if(!this.showPrimarySchools){
						continue;
					}
					icon = this.primarySchoolIcon;
				}

				schoolNode = new RPWGoogleMapSchoolInfoObject(this.schoolData[i]);
				schoolNode.displayContent();

				point = new GLatLng(this.schoolData[i].LATITUDE,this.schoolData[i].LONGITUDE);

				marker = this.createGMapMarker(point, schoolNode.domElement, icon);

				markerManager.addMarker(marker,this.schoolMinZoom);

			}

			markerManager.refresh();

		}

	}

	// STATIONS

	this.getStationMarkerManager = function(){

		if(this.stationMarkerManager == null){
			this.stationMarkerManager = new MarkerManager(this.gMapObj);
		}

		return this.stationMarkerManager;
	}

	this.clearStations = function(){
		if(this.stationMarkerManager != null){
			this.stationMarkerManager.clearMarkers();
			this.stationMarkerManager.refresh();
		}
		this.stationData = null;
	}

	this.toggleStationInfo = function(input){

		this.parentObj.savePreference("RPWGoogleMapObject.showStationInfo",Number(input.getValue()));

		this.showStationInfo = input.getValue();
		if(this.stationMarkerManager != null){
			this.stationMarkerManager.clearMarkers();
			this.stationMarkerManager.refresh();
		}
		if(input.getValue() && this.stationData == null){
			this.loadStations();
		}else{
			this.displayStations();
		}

	}

	this.loadStations = function(){

		if(this.showStationInfo && this.gMapObj.getZoom() >= this.stationMinZoom){

			var bounds = this.gMapObj.getBounds();

			var sw = bounds.getSouthWest();
			var ne = bounds.getNorthEast();

			var lat1 = Math.min(sw.lat(),ne.lat());
			var lat2 = Math.max(sw.lat(),ne.lat());
			var lng1 = Math.min(sw.lng(),ne.lng());
			var lng2 = Math.max(sw.lng(),ne.lng());


			var thisObj = this;

			var onLoadFunc = function(data){ thisObj.displayStations(data);};

			RPWSearchSocket.getStations(lat1,lat2,lng1,lng2,onLoadFunc);

		}

	}


	this.displayStations = function(data){

		if(data != null){
			if(this.dataObject == null){
				this.dataObject = new Object();
			}
			this.stationData = data.stations;
		}

		//alert("Data: "+this.stationData+", Length: "+this.stationData.length+", Primary stations: "+this.showPrimaryStations+", Secondary stations: "+this.showSecondaryStations);


		if(this.stationData != null && this.stationData.length > 0 && this.showStationInfo){

			if(this.stationMarkerManager != null){
				this.stationMarkerManager.clearMarkers();
				this.stationMarkerManager.refresh();
			}

			var stationNode;
			var point;
			var icon;
			var marker;

			var markerManager = this.getStationMarkerManager();

			for(var i in this.stationData){

				icon = this.stationInfoIcon;

				stationNode = new RPWGoogleMapStationInfoObject(this.stationData[i]);
				stationNode.displayContent();

				point = new GLatLng(this.stationData[i].latitude,this.stationData[i].longitude);

				marker = this.createGMapMarker(point, stationNode.domElement, icon);

				markerManager.addMarker(marker,this.stationMinZoom);

			}

			markerManager.refresh();

		}

	}


	// OFFICES

	this.getOfficeMarkerManager = function(){

		if(this.officeMarkerManager == null){
			this.officeMarkerManager = new MarkerManager(this.gMapObj);
		}

		return this.officeMarkerManager;
	}


	this.toggleOffices = function(input){

		this.parentObj.savePreference("RPWGoogleMapObject.showOffices",Number(input.getValue()));

		this.showOffices = input.getValue();
		if(this.officeMarkerManager != null){
			this.officeMarkerManager.clearMarkers();
			this.officeMarkerManager.refresh();
		}
		this.displayOffices();

	}


	this.loadOffices = function(){

		var bounds = this.gMapObj.getBounds();

		var sw = bounds.getSouthWest();
		var ne = bounds.getNorthEast();

		var lat1 = Math.min(sw.lat(),ne.lat());
		var lat2 = Math.max(sw.lat(),ne.lat());
		var lng1 = Math.min(sw.lng(),ne.lng());
		var lng2 = Math.max(sw.lng(),ne.lng());


		var thisObj = this;

		var onLoadFunc = function(data){ thisObj.displayOffices(data);};

		RPWSearchSocket.getOffices(lat1,lat2,lng1,lng2,onLoadFunc);

	}

	this.displayOffices = function(data){

		if(data != null){
			if(this.dataObject == null){
				this.dataObject = new Object();
			}
			this.dataObject.offices = data.offices;
		}

		if(this.dataObject != null && this.dataObject.offices != null && this.dataObject.offices.length > 0 && this.showOffices){

			var officeNode;
			var point;
			var icon;
			var marker;

			if(this.officeMarkerManager != null){
				this.officeMarkerManager.clearMarkers();
				this.officeMarkerManager.refresh();
			}

			var markerManager = this.getOfficeMarkerManager();

			var officeSet = new Object();

			for (var i in this.dataObject.offices) {

				if (officeSet[this.dataObject.offices[i].postcode] == null) {
					officeSet[this.dataObject.offices[i].postcode] = new Object();
					officeSet[this.dataObject.offices[i].postcode].nodes = new Array();
					officeSet[this.dataObject.offices[i].postcode].point = new GLatLng(this.dataObject.offices[i].latitude, this.dataObject.offices[i].longitude);
				}

				officeNode = new RPWGoogleMapOfficeInfoObject(this.dataObject.offices[i]);
				officeNode.setParent(this);
				officeNode.displayContent();

				officeSet[this.dataObject.offices[i].postcode].nodes.push(officeNode.domElement);

			}

			var div, j;

			for(i in officeSet){

				div = document.createElement("div");

				for(j=0;j<officeSet[i].nodes.length;j++){

					div.appendChild(officeSet[i].nodes[j]);

				}

				icon = this.officeIcon;

				marker = this.createGMapMarker(officeSet[i].point, div, icon);

				markerManager.addMarker(marker,4);

			}

			markerManager.refresh();

		}

	}




	this.RPWGoogleMapObject();


}

RPWGoogleMapObject.inherits(DisplayObject);


function RPWGoogleMapPropertyInfoObject(dataObject){

	DisplayObject.call(this);

	this.dataObject = dataObject;
	this.saveButton = null;

	this.createDOMElement("div");


	this.displayContent = function(hideImage){

		this.clearContents();

		if (!this.getAttribute("RPWGoogleMapObject.thumbnailWidth")) {
			this.setAttribute("RPWGoogleMapObject.thumbnailWidth", 120);
			this.setAttribute("RPWGoogleMapObject.thumbnailHeight", 90);
		}

		/*var tr = this.addElement("tr");

		var cell1 = document.createElement("td");
		cell1.className = "textCell";
		tr.appendChild(cell1);

		var cell2 = document.createElement("td");
		cell2.className = "imageCell";
		tr.appendChild(cell2);*/

		// add image
		if(hideImage != true && this.dataObject.images != null){

			var imageNode  = document.createElement("img");
			imageNode.setAttribute("width",this.getAttribute("RPWGoogleMapObject.thumbnailWidth"));
			imageNode.setAttribute("height",this.getAttribute("RPWGoogleMapObject.thumbnailHeight"));
			imageNode.setAttribute("src",httpRoot+"index.php?action=getthumbnail&filepath="+this.dataObject.images[0].filepath+"&width="+this.getAttribute("RPWGoogleMapObject.thumbnailWidth")+"&height="+this.getAttribute("RPWGoogleMapObject.thumbnailHeight")+"&quality=75&crop=1");
			imageNode.style.width = this.getAttribute("RPWGoogleMapObject.thumbnailWidth")+"px";
			imageNode.style.height = this.getAttribute("RPWGoogleMapObject.thumbnailHeight")+"px";
			imageNode.style.cssFloat = "right";
			this.domElement.appendChild(imageNode);
		}

		// add price
		var priceNode = document.createElement("h5");
		priceNode.innerHTML = this.dataObject.price;
		this.domElement.appendChild(priceNode);
		// add status

		if(this.dataObject.status != null){
			priceNode.appendChild(document.createTextNode(" "));
			var statusNode = priceNode.appendChild(document.createElement("strong"));
			statusNode.innerHTML = this.dataObject.status;

		}


		// add address

		var titleNode = document.createElement("p");

		titleNode.appendChild(document.createTextNode(this.dataObject.address));
		this.domElement.appendChild(titleNode);

		// add rooms


		if(this.dataObject.rooms != null){

			var element = document.createElement("ul");

			element.className = "roomList";

			var roomItem;

			for(var i in this.dataObject.rooms){

				roomItem = document.createElement("li");
				roomItem.title = this.dataObject.rooms[i]+" "+i;
				roomItem.className = String(i).replace(/\(?s\)?$/gi,"").toLowerCase();
				roomItem.innerHTML = this.dataObject.rooms[i]+" <span>"+i+"</span>";

				element.appendChild(roomItem);

			}

			this.domElement.appendChild(element);

		}


		// add details link

		var thisObj = this;

		var detailsAction = function(){thisObj.showDetails()};

		var optionButtonNode = document.createElement("p");
		this.domElement.appendChild(optionButtonNode);
		optionButtonNode.className = "optionButtons";
		var detailsNode = optionButtonNode.appendChild(document.createElement("a"));
		detailsNode.className = "pOptionButton showDetails";
		detailsNode.setAttribute("href","javascript:void(0);");
		detailsNode.onclick = detailsAction;
		detailsNode.innerHTML = "<span>More details</span>";

		// add save link

		this.addText(" ");

		this.saveButton = optionButtonNode.appendChild(document.createElement("a"));

		this.saveButton.setAttribute("href","javascript:void(0);");

		var thisObj = this;
		this.saveButton.onclick = function(e){thisObj.toggleSaved(e);this.blur();};

		this.saveButton.innerHTML = "<span>Save to shortlist</span>";
		this.saveButton.className = "pOptionButton saveToShortlist";
		this.saveButton.title = "Save to shortlist";

		this.markAsSaved(this.parentObj.parentObj.propertyIsSaved(this.dataObject));

		var br = this.addElement("br");
		br.style.clear = "both";

		this.setStyle("height",(Number(this.getAttribute("RPWGoogleMapObject.thumbnailHeight"))+20)+"px");
		this.setStyle("overflow","hidden");

	}

	this.showDetails = function(){

		this.parentObj.parentObj.showPropertyDetails(this.dataObject)

	}

	this.toggleSaved = function(e){

		if(!this.parentObj.parentObj.propertyIsSaved(this.dataObject)){


			this.parentObj.parentObj.saveProperty(this.dataObject);

		}else{

			this.parentObj.parentObj.removeSavedProperty(this.dataObject);

		}

	}

	this.markAsSaved = function(saved){

		if(saved){
			this.saveButton.className = "pOptionButton removeFromShortlist";
			this.saveButton.title = "Remove from shortlist";
			this.saveButton.innerHTML = "<span>Remove from shortlist</span>";
		}else{
			this.saveButton.className = "pOptionButton saveToShortlist";
			this.saveButton.title = "Save to shortlist";
			this.saveButton.innerHTML = "<span>Save to shortlist</span>";
		}
	}




}

RPWGoogleMapPropertyInfoObject.inherits(DisplayObject);


function RPWGoogleMapSchoolInfoObject(dataObject){

	DisplayObject.call(this);

	this.dataObject = dataObject;

	this.createDOMElement("p");

	this.displayContent = function(){

		this.clearContents();

		this.addElement("strong",this.dataObject.SCHOOL_NAME);
		this.addElement("br");
		this.addText(this.dataObject.STREET+", "+this.dataObject.LOCALITY);
		this.addElement("br");
		this.addText("Ages: ");
		this.addElement("strong",this.dataObject.STAT_LOW_AGE+" - "+this.dataObject.STAT_HIGH_AGE)
		this.addElement("br");
		this.addText("Tel: ");
		this.addElement("strong","0"+this.dataObject.TEL_STD+" "+this.dataObject.TEL_NO);
	}


}

RPWGoogleMapSchoolInfoObject.inherits(DisplayObject);

function RPWGoogleMapOfficeInfoObject(dataObject){

	DisplayObject.call(this);

	this.dataObject = dataObject;

	this.createDOMElement("div");
	this.domElement.className = "gMapInfoWindow office";

	this.displayContent = function(){

		this.clearContents();

		if (!this.getAttribute("RPWGoogleMapObject.thumbnailWidth")) {
			this.setAttribute("RPWGoogleMapObject.thumbnailWidth", 120);
			this.setAttribute("RPWGoogleMapObject.thumbnailHeight", 90);
		}

		// add image
		if(this.dataObject.images != null){
			var imageNode  = this.addElement("img");
			imageNode.setAttribute("src",httpRoot+"index.php?action=getthumbnail&filepath="+this.dataObject.images[0].filepath+"&width="+this.getAttribute("RPWGoogleMapObject.thumbnailWidth")+"&height="+this.getAttribute("RPWGoogleMapObject.thumbnailHeight")+"&quality=75&crop=1");
			imageNode.setAttribute("width",this.getAttribute("RPWGoogleMapObject.thumbnailWidth"));
			imageNode.setAttribute("height",this.getAttribute("RPWGoogleMapObject.thumbnailHeight"));

			this.setStyle("width","400px");

		}

		this.setStyle("height",(this.getAttribute("RPWGoogleMapObject.thumbnailHeight")+20)+"px");

		this.addElement("h5",this.dataObject.name);
		this.addText(this.dataObject.address);
		if(this.dataObject.telephone != null){
			this.addElement("br");
			this.addText("Tel: ");
			this.addElement("strong",this.dataObject.telephone);
		}
		if(this.dataObject.fax != null){
			this.addElement("br");
			this.addText("Fax: ");
			this.addElement("strong",this.dataObject.fax);
		}
		if(this.dataObject.email != null){
			this.addElement("br");
			this.addText("Email: ");
			var emailElement = this.addElement("a",this.dataObject.email);
			emailElement.setAttribute("href","mailto:"+this.dataObject.email);
		}
	}


}

RPWGoogleMapOfficeInfoObject.inherits(DisplayObject);

function RPWGoogleMapStationInfoObject(dataObject){

	DisplayObject.call(this);

	this.dataObject = dataObject;

	this.createDOMElement("p");

	this.displayContent = function(){

		this.clearContents();

		this.addElement("strong",this.dataObject.station+" Station");
		this.addElement("br");
		if(this.dataObject.code != null && this.dataObject.code != ""){
			var depLink = this.addElement("a");
			depLink.setAttribute("href","http://www.livedepartureboards.co.uk/ldb/summary.aspx?T="+this.dataObject.code);
			depLink.innerHTML = "Departure times";
			depLink.setAttribute("title","Click here for destinations from this station.");
			depLink.setAttribute("target","RPWDepartureWindow");
		}
	}


}

RPWGoogleMapStationInfoObject.inherits(DisplayObject);

initLiveList();
