var httpRoot = "http://www.frankmason.co.uk//";
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;

}

function clearForm(form){
	for (var i = 0; i < form.elements.length; i++){
	    switch (form.elements[i].type.toLowerCase()){
		    case "text":
		    case "password":
		    case "textarea":
		    case "hidden":
		        form.elements[i].value = "";
		        break;

		    case "radio":
		    case "checkbox":
		        if (form.elements[i].checked){
		            form.elements[i].checked = false;
		        }
		        break;

		    case "select":
		    case "select-one":
		    case "select-multi":
		        form.elements[i].selectedIndex = 0;
		        break;
		    default:
		        break;
	    }
	}
}



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

function includeJS(script_filename) {
	document.write("<script 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, phpSessionID){

	this.httpRoot = httpRoot;

	this.phpSessionID = phpSessionID;

	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 = dataStr.replace( /\uC3A3/g,"GBPOUNDSIGN");
			dataStr = dataStr.replace( /\\xA3/g,"GBPOUNDSIGN");
			//dataStr = dataStr.replace( /\\xA3/g,"GBPOUNDSIGN");


			dataStr = escape(dataStr);


			dataStr = dataStr.replace( /GBPOUNDSIGN/g,"%A3");

			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;
	   }
	}

	this.post = function(url,data,callback,timeout){

		if(typeof(JSONRequest) == "undefined"){
			alert("JSONRequest object must be loaded before posting data.");
			return;
		}

		JSONRequest.post(url,data,callback,timeout);

	}

}

/*if(typeof(httpRoot) == "undefined" && typeof(DTDSiteRoot) != "undefined"){
	var httpRoot = DTDSiteRoot;
}*/

if(typeof(phpSessionID) == "undefined"){
	phpSessionID = null;
}


var JSONSocket = new JSONSocketObject(httpRoot, phpSessionID);

// 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.transformationEndFunctions = new Object;

	this.displayStyle = null;

	this.toggledOpen = true;

	// 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;
		}

		if(domElement){

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

		}

		return null;

	}



	/// 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.getRandomNumber = function(range){
		return Math.floor(Math.random() * range);
	}

	this.getRandomChar = function(){
		var chars = "0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
		return chars.substr(this.getRandomNumber(62), 1 );
	}

	this.getRandomID = function(size){
		size = (size == null) ? 32 : size;
		var str = "";
		for(var i = 0; i < size; i++){
			str += this.getRandomChar();
		}
		return str;
	}


	this.setHTML = function(html){

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

	}

	// Child methods

	this.addDisplayObject = function(tag, className){

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

		if(className != null){
			displayObject.setClass(className);
		}

		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 [3] 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){

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

			this.domElement.removeChild(element);

		}

	}

	this.remove = function(){
		if(typeof(this.domElement.parentNode) != 'undefined'){
			this.domElement.parentNode.removeChild(this.domElement);
		}
	}

	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.domElement != null && this.domElement.parentNode == element){

			element.removeChild(this.getDOMElement());

		}

	}

	this.detach = function(){
		if(this.domElement != null && this.domElement.parentNode != null){
			this.domElement.parentNode.removeChild(this.domElement);
		}
	}

	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;
		}


		if (opacity == 100 && element.style.removeAttribute != null) {
			element.style.removeAttribute('filter');
		} else {
			element.style.filter='progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity + ')';
			//element.style.filter = "alpha(style=0,opacity:" + opacity + ")"; // <=IE7
		}
		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, callback){

		if(callback != null){
			this.transformationEndFunctions["opacity"] = callback;
		}

		increment = (increment == null) ? 10 : increment;
		var i = 0;
		// determine the direction for the blending
		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{
			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++;
			}
		}

		while(typeof(this.transformations[i]) != "undefined" && typeof(this.transformations[i]["opacity"]) != "undefined"){// remove remaining old transformations
			delete(this.transformations[i]["opacity"]);
			i++;
		}

		this.startTransform();
	}

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

		this.transformationEndFunctions[dimension] = callback;

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

		var oldValue = (this.domElement.style[dimension] && !isNaN(parseInt(this.domElement.style[dimension].replace(/[^\d-\.]/,'')))) ? parseInt(this.domElement.style[dimension].replace(/[^\d-\.]/,'')) : 0;

		//alert(dimension+" from "+oldValue+" to "+newValue);

		var change = newValue-oldValue;

		var increment = change/steps;

		for(var i=0;i<steps;i++){
			if(this.transformations[i] == null){
				this.transformations[i] = new Object();
			}
			if(easing && easing.toLowerCase() == "in"){
				this.transformations[i][dimension] = this.easeInQuad(i,oldValue,change,steps)
			}else if(easing && easing.toLowerCase() == "out"){
				this.transformations[i][dimension] = this.easeOutQuad(i,oldValue,change,steps)
			}else{
				this.transformations[i][dimension] = oldValue + increment*(i+1);
			}
		}

		while(typeof(this.transformations[i]) != "undefined" && typeof(this.transformations[i][dimension]) != "undefined"){// remove remaining old transformations
			delete(this.transformations[i][dimension]);
			i++;
		}

		this.startTransform();
	}


	this.slideToggle = function(speed,easing,callback,direction){

		if(typeof(jQuery) != "undefined"){

			var element = this.domElement;

			if(direction == "show"){
				$(element).slideDown(speed,easing,callback);
			}else if(direction == "hide"){
				$(element).slideUp(speed,easing,callback);
			}else{
				$(element).slideToggle(speed,easing,callback);
			}

			return;

		}

		if(direction == null){
			direction = (this.toggledOpen) ? "hide" : "show"
		}

		if(direction == "show" && !this.toggledOpen){

			this.show();
			if(callback != null){
				callback(this);
			}
			this.toggledOpen = true;

		}else if(this.toggledOpen){

			this.hide();
			if (callback != null) {
				callback(this);
			}
			this.toggledOpen = false;

		}
	}


	this.startTransform = function(){

		if(!this.transformationStarted){

		var thisObj = this;

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

		this.transformationStarted = true;

		}

	}

	this.show = function(){

		if(typeof(jQuery) != null){
			$(this.domElement).show();
			return;
		}

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

	}

	this.hide = function(){

		if(typeof(jQuery) != null){
			$(this.domElement).hide();
			return;
		}

		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 || typeof(this.transformations[0][i]) == "undefined") && this.transformationEndFunctions[i] != null){
					this.transformationEndFunctions[i](this);
				}

			}

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

		}

	}

	// 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 = null;

			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;

	}

}


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);

function ImageSlideShowObject(dataObject){

	DisplayObject.call(this);

	// create container

	// sub-elements
	this.dataObject = dataObject;
	this.optionButtonsElement = 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.onRemoveFunction = null;

	this.overlay = null;

	//

	this.ImageSlideShowObject = 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.imageTotal = this.dataObject.images.length;
		}



		this.createDOMElement("div","ImageSlideShowObject");
		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(){

		this.displayOverlay();

		this.clearContents();

		this.addCloseButton();

		this.addStatusElement();

		if(this.imageArray.length > 0){

			this.loadImage(this.imagePointer);

			// add navigation

			if(this.imageArray.length > 1){

				this.addNavigation();


			}


		}

		this.setStyle("z-index",1010);

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

		this.appendToElement(bodyObj);


	}

	this.remove = function(e){

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

		this.removeOverlay();

		if(this.onRemoveFunction != null){
			this.onRemoveFunction(this);
		}

	}

	this.displayOverlay = function(){

		this.overlay = new OverlayObject();
		var thisObj = this;
		this.overlay.onRemoveFunction = function(){ thisObj.remove();};
		this.overlay.displayContent();

	}

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


	/// IMAGE METHODS

	this.loadImage = function(index){

		this.imagePointer = index;

		if(this.imageArray[index] != null){



			var newImage = new SlideShowImageObject(this.imageArray[index]);
			var status = "Image "+(index+1)+" of "+this.imageTotal;
			status = (this.imageArray[index].caption) ? this.imageArray[index].caption+" ("+status+")" : status;
			this.setStatus(status);

			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.transformationEndFunctions["opacity"] = func;

				this.currentImageObject.changeOpacity(0);
			}

			this.currentImageObject = newImage;

		}
	}

	this.unloadImage = function(imageObject){

		imageObject.removeFromElement(this.domElement);

	}


	// 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.ImageSlideShowObject();

}

ImageSlideShowObject.inherits(DisplayObject);


function SlideShowImageObject(dataObject){

	DisplayObject.call(this);

	this.dataObject = dataObject;

	// Constructor

	this.SlideShowImageObject = function(){

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

	}

	this.displayContent = function(maxWidth,maxHeight,crop){

		// add image

		this.imageElement = this.addElement("img",null,"src",httpRoot+unescape(this.dataObject.thumbnail)+"&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");


	}

	this.SlideShowImageObject();

}

SlideShowImageObject.inherits(DisplayObject);



