/*
 *	RenaissanceCMS
 *	RenFront.js | core version | last modified 08/11/08
 *  
 *	Renaissance framework for the front end
 * 
 */

var RenFront={};

RenFront.Content={};
RenFront.Interactive={};

RenFront.Content.openContent={};

RenFront.Content.fetch=function(id,type,view,target,background,close_link){

	this.openContent[target]={background: background, close_link: close_link};
	
	var url=sys.path+'_content/'+id+'/'+type+'/'+view;

	var updater = new Ajax('get', url, {onSuccess: RenFront.Content.onUpdate, params: [target]});
	updater.update(target);

	fader(target,-1,0,100,0);
}

RenFront.Content.addCloseLink=function(target){

	var close_link=RenFront.Content.openContent[target].close_link;
	var link={tag: 'A', title: close_link, href: 'javascript:RenFront.Content.closeContent("'+target+'")', className: "interface content_close_link", text: close_link};
	ElementHandler.putAtEnd(target,link);
}

RenFront.Content.closeContent=function(target){

	fader(target,-1,0,100,1);

	if(RenFront.Content.openContent[target].background)
		fader(RenFront.Content.openContent[target].background,-0.5,0,75,1);
}

RenFront.Content.onUpdate=function(target,rObject){

	if(RenFront.Content.openContent[target].close_link)
		RenFront.Content.addCloseLink(target);

	fader(target,1,100,0,0);

	if(RenFront.Content.openContent[target].background)
		fader(RenFront.Content.openContent[target].background,0.5,75,0,1);

}


function RenDebugConsole(){

	this.initialize();
}

RenDebugConsole.prototype={
	
	initialize: function(){
		
		this.name_space='ren-';
		
	},

	show: function(item){
		
		var obj=$.id(this.name_space+item,'animation');

		if(!obj.shown || typeof obj.shown=='undefined')
			{
			obj.fade.start([1,0],0.3,{display: true});
			obj.shown=true;
			}
		else
			{
			obj.fade.start([0,1],0.1,{display: true});
			obj.shown=false;
			}

	}
	
	
}

	/*
	=:project
	  RenaissanceCMS

	=:class
	  RenSlideShow

	=:since
	  0.3.1a

	=:last update
	  06/02/09

	=:status
	  in progress

	=:principle author
	  Rob chant

	=:notes
      JavaScript part of renaissance's slideshow functionality

	=:contains methods

		=:public
		  
		
		=:private


	=:contains properties

		=:public
		
		=:private


 	=:contains methods

		=:public
		  RenSlideShow(id,target,view,initial_image,use_activation,activated)

		=:private
		  activate()
		  deActivate()
		  initialize()
		  showImage(image)

	*/

function RenSlideShow(id,target,view,initial_image,use_activation,activated){

	this.initialize(id,target,view,initial_image,use_activation,activated);
}

RenSlideShow.prototype={
	
	id: null,
	target: null,
	view: null,
	use_activation: null,
	
	current: null,
	activated: null,

	initialize: function(id,target,view,initial_image,use_activation,activated){
		
		this.id=id;
		this.target=target;
		this.view=view;
		this.use_activation=use_activation;

		this.current=initial_image;
		this.activated=activated;

	},

	activate: function(){
	
		if(this.use_activation)
			{
			if(!this.activated)
				{
				$.id(this.target).style.display='block';
				this.activated=true;
				}
			}
	},

	deActivate: function(){
		
		if(this.use_activation)
			{
			if(this.activated)
				{
				$.id(this.target).style.display='none';
				this.activated=false;
			
				if(typeof this.current=='number')
					{	
					DomUtils.removeClassName('slide-show-'+this.id+'-activation-'+this.current,'on');
					this.current=false;
					
					$.id(this.target).innerHTML='';
					}
				}
			}
		
	},

	showImage: function(image){

		if(this.current!=image)
			{
			RenFront.Content.fetch(image,'image',this.view,this.target,'','');

			this.activate();

			if(typeof this.current=='number')
				DomUtils.removeClassName('slide-show-'+this.id+'-activation-'+this.current,'on');

			DomUtils.addClassName('slide-show-'+this.id+'-activation-'+image,'on');
		
			this.current=image;
			}
		else
			this.deActivate();
	}	

}

	
	Inheritence = function() {

		return {
			
			extend: function(inheriter, inheritee) {
						
				for(property in inheritee) 
					inheriter[property] = inheritee[property];

				return inheriter;
			}
		}
	}();
	
	DomUtils = function () {

		return {

			/* Gets previous sibling ignoring empty text nodes
				Gets previous
				If text node gets previous again */
				
			getPrevious: function(el) {
							 
				var previous = $.id(el).previousSibling;
				
				while(previous.nodeType == 3)
					previous = previous.previousSibling;
				
				return previous;
			},

			/* Gets next sibling ignoring empty text nodes
				Gets next
				If text node gets previous again */
							 
			getNext: function(el) {	
						 
				var next = $.id(el).nextSibling;
				
				while(next.nodeType == 3)
					next = next.nextSibling;
				
				return next;
			},

			/* Gets all children ignoring text nodes. Returns array
				Gets all children
				Makes new array
				Loops through children and pushes non-text nodes into the array */			

			getChildren: function(el) {
							 
				var parent = $.id(el);
				var allChildren = parent.childNodes;
				var children = new Array();
				
				for(var i = 0; i < allChildren.length; i++) {
					if(allChildren[i].nodeType != 3)
						children.push(allChildren[i]);
				}

				return children;
			},

			getViewXY: function() {

				var x,y;
				
				if (self.innerHeight) {
					x = self.innerWidth;
					y = self.innerHeight;
				}
				
				else if (document.documentElement && document.documentElement.clientHeight) {
					x = document.documentElement.clientWidth;
					y = document.documentElement.clientHeight;
				}
				
				else if (document.body) {
					x = document.body.clientWidth;
					y = document.body.clientHeight;
				}

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


			getDocXY: function() {

				var margin = parseInt(DomUtils.getStyle(document.body,'margin-bottom')) + parseInt(DomUtils.getStyle(document.body,'margin-top'));
	
				var Xa = (Xa = document.documentElement.clientWidth)? Xa: -1; //IE and Mozilla window width
				var Xb = (Xb = document.body.offsetWidth + margin)? Xb: -1; //IE and Mozilla document width
				var Xc = (Xc = document.body.clientWidth)? Xc: -1; //exceptions
				var Xd = (Xd = document.body.scrollWidth)? Xd: -1; //exceptions
				var Xe = (Xe = self.innerWidth)? Xe: -1; //alt IE and Mozilla window width

				var sortedX = [Xa,Xb,Xc,Xd,Xe].sortNumb(); //sort all possible widths

				var Ya = (Ya = window.innerHeight + window.scrollMaxY)? Ya: -1; //IE and Mozilla scroll height
				var Yb = (Yb = document.documentElement.clientHeight)? Yb: -1;  //IE and Mozilla window height
				var Yc = (Yc = document.documentElement.scrollHeight)? Yc: -1; //Opera and Safari scroll height
				var Yd = (Yd = document.body.offsetHeight + margin)? Yd: -1; //IE and Mozilla body height
				var Ye = (Ye = document.body.scrollHeight)? Ye: -1; //exceptions
				var Yf = (Yf = document.body.clientHeight)? Yf: -1; //exceptions
				var Yg = (Yg = self.innerHeight)? Yg: -1; //alt IE and Mozilla window height

				var sortedY = [Ya,Yb,Yc,Yd,Ye,Yf,Yg].sortNumb(); //sort all possible heights

				return {x: sortedX[sortedX.length-1], y: sortedY[sortedY.length-1]} //return largest width and largest height
			},

			getScroll: function() {

				var l,t;

				if(document.documentElement && document.documentElement.scrollLeft) {
					l = document.documentElement.scrollLeft;
					t = document.documentElement.scrollTop;
				}
				
				else if(document.body) {
					l = document.body.scrollLeft;
					t = document.body.scrollTop;
				}
				
				return {l: l, t: t};
			},

			getTrueOffset: function(el) {
							   
				var el = $.id(el);
				var l = 0, t = 0;
				
				do {
					l += el.offsetLeft || 0;
					t += el.offsetTop || 0;
					el = el.offsetParent;
				}
				while (el);
				
				return {l: l, t: t};
			},	

			getPosOffset: function(el) {

				var el = $.id(el);
				var l = el.offsetLeft + document.body.offsetLeft;
				var t = el.offsetTop + document.body.offsetTop;
				var parent = el.parentNode;

				while (parent.nodeName != 'BODY') {
					var ps = DomUtils.getStyle(parent,'position')

					if(ps == 'absolute' || ps == 'relative')
						break;

					l += parent.offsetLeft || 0;
					t += parent.offsetTop || 0;

					parent = parent.parentNode;
				}

				return {l: l, t: t};
			},

			makeAbsolute: function(el, complete) {

				var el = $.id(el);

				if(el.style.position == 'absolute')
					return;

				el.oldLeft = DomUtils.getStyle(el,'left');
				el.oldTop = DomUtils.getStyle(el,'top');
				el.oldWidth = DomUtils.getStyle(el,'width');
				el.oldHeight = DomUtils.getStyle(el,'height');
				el.oldParent = el.parentNode;
				el.oldSibling = el.nextSibling;

				var offset = (complete == true)? DomUtils.getTrueOffset(el): DomUtils.getPosOffset(el);
				var left = offset.l;
				var top = offset.t;
				var width = el.clientWidth;
				var height = el.clientHeight;

				el.style.position = 'absolute';
				el.style.left = left + 'px';
				el.style.top = top + 'px';
				el.style.width = width + 'px';
				el.style.height = height + 'px';
			},

			makeRelative: function(el) {

				var el = $.id(el);

				if(el.style.position == 'relative')
					return;

				el.style.position = 'relative';
				el.style.left = el.oldLeft;
				el.style.top = el.oldTop;
				el.style.width = el.oldWidth;
				el.style.height = el.oldHeight;
			},

			setAnyAttribute: function(el,attribute,value) {

				var el = $.id(el);

				switch(attribute) {
					
					case "style":
						document.all?
							el.style.setAttribute("cssText", value):
							el.setAttribute("style", value);
							break;
							
					case "className":
						document.all?
							el.setAttribute("className", value):
							el.setAttribute("class", value);
							break;	    
							
					default:
						el.setAttribute(attribute, value);
				}
			},

			getAnyAttribute: function(el,attribute) {

				var el = $.id(el);
				if(!el)
					return false;

				switch(attribute) {
					
					case "style":
						var value = document.all?
							el.style.getAttribute("cssText"):
							el.getAttribute("style");
							break;
							
					case "class":
						value = document.all?
							el.getAttribute("className"):
							el.getAttribute("class");
							break;

					default:
						value = el.getAttribute(attribute);
				}

				return value;
			},

			//Equalises 'getComputedStyle(') W3 DOM method, 'currentStyle' property of Microsoft, and 'style' property
			getStyle: function(el,property) {
	
				var el = $.id(el);
				var styleList;
				var value = el.style[property.toFirstUpper()];

				if(!value) {
					if (document.defaultView && document.defaultView.getComputedStyle) {
						styleList = document.defaultView.getComputedStyle(el,null);
						value = styleList.getPropertyValue(property);
						value = value.toFirstUpper();
					}

					else if(el.currentStyle) 
						value = el.currentStyle[property.toFirstUpper()]
				}

				return value == 'auto'? null: value;    
			},
	
			//equalises IE and W3 DOM opacity settings
			setStyle: function(el,property,value) {

				var el = $.id(el);
				var property = property.toFirstUpper();

				if(property == 'opacity') {
					el.style.opacity = value;
					el.style.filter = "alpha(opacity=" + value * 100 + ")";
				}

				else 
					el.style[property] = value;
			},

			addClassName: function(element, className) {
				if(!$.id(element))
					return;
				var string = this.getAnyAttribute(element, 'class');
				if(string==null || string.indexOf(className) == -1)
					string += ' ' + className;
				this.setAnyAttribute(element, 'className', string)
			},
			
			removeClassName: function(element, className) {
				if(!$.id(element))
					return;
				var string = this.getAnyAttribute(element, 'class');
				if(string == false)
					return;
				string = string.replace(className, '');
				this.setAnyAttribute(element, 'className', string);
			},

			//**** NEEDS TO COME OUT. Need seperate Animation and Fade class ****/
			fade: function (el, dir, vis, time, step, end) { 
				var obj = $.id(el);
				if (typeof time == 'undefined') time = 100;
				if (typeof step == 'undefined') step = 100;
				if (typeof end == 'undefined' && dir > 0) end = 0.9999;
				if (typeof end == 'undefined' && dir < 0) end = 0;
	    
				if(obj.timer == null) {
					obj.timer=0;
					obj.opacity=0;
				}

				if(obj.timer!==0) {
					clearInterval(obj.timer);
					obj.timer=0;
				}
	    
				if(obj.style.visibility !== 'visible') 
					obj.style.visibility = 'visible';
				
				obj.timer = setInterval(fadeloop, time/step);
	   
				function fadeloop() {
					obj.opacity += dir/step;
					if ((dir > 0 && obj.opacity >= end) || (dir < 0 && obj.opacity <=end)) {
						obj.opacity = end;
							if(typeof vis !== undefined) {
								obj.style.visibility = vis;
								clearInterval(obj.timer);
							}
					}
					obj.style.opacity = obj.opacity;
					obj.style.filter = "alpha(opacity=" + obj.opacity * 100 + ")";
				}
			},

			//**** Maybe unnecessary but if keep should probably go in ElementHandler ****/
			swap: function(el, newPlace) {	

				var current = $.id(el);
				var parent = current.parentNode;
				var other = $.id(newPlace);
				var current_new = current.cloneNode(true);
				var other_new = other.cloneNode(true);
	    
				parent.replaceChild(current_new, other);
				parent.replaceChild(other_new, current);
			},

			//**** Decide what to do with these when redo Display. Something needs to lose them, or inherit ****/
			show: function() {

				for(var i = 0; i < arguments.length; i++) {
					var el = $.id(arguments[i]);

					el.style.visibility = 'visible';
					el.style.display = 'block';
				}
			},

			hide: function() {

				for(var i = 0; i < arguments.length-1; i++) {
					var el = $.id(arguments[i]);

					el.style.visibilty = 'hidden';
					if(arguments[arguments.length-1] == true)
						el.style.display = 'none';
				}
			}
	    }

	}();

	
		
	Inheritence.extend(Array.prototype, {

		/* Calls passed in function for each item in the array, where 'item' and 'value' can be parameters of the function
		passed in */

		foreach: function(iterator) {
			
			for(var i = 0; i < this.length; i++)
				iterator(i, this[i]);
		},

		indexOf: function(object) {
		
			for (var i = 0; i < this.length; i++)
				if (this[i] == object) return i;
			return -1;
		},

		/* Rotates an array taking off last item and adding it to front */
			
		rotateBack: function() {
		
			return this.unshift(this.pop());
		},

		/* Rotates an array taking off first item and appending it */
		
		rotateForw: function() {
		
			return this.push(this.shift());
		},	

		/* Swaps two items of an array */
		
		swap: function(a,b) {

			var temp = this[a];

			this[a] = this[b];
			this[b] = temp;
		},

			  
		sortNumb: function(numb) {
			
			/* Comparison function required by JavaScript's native sort */		  
					  
			function comparison(a,b) {

				return (a-b);
			}
			
			var numb = numb || null;
			
			/* Sorts the array */
			
			var list = this.sort(comparison);
			
			switch(numb) {

				/* Returns whole array if no argument passed */
				
				case(null):	
					return list;

				/* Returns minimum value */	
					
				case('min'):
					return list[list.length-1];
			
				/* Returns maximum value */
					
				case('max'):
					return list[0];
				
				/* If a number passed returns that number in the array */	
					
				default:
					return list[numb];
			}	
		}
	});
	
	function FuncArray() {
	
		for(var i = 0; i < arguments.length; i++)
			this.list.push(arguments[i]);
	
	}
		
	FuncArray.prototype = {
	
		list: [],
		
		test: function() {
		    var result;
		    
		    for (var i = 0, n = this.list; i < n.length; i++) {
		      try {
		        result = n[i]();
		        break;
		      } catch (e) {}
		    }
		    
		    return result;
		}
	} 
	
	Inheritence.extend(FuncArray.prototype, Array.prototype);

	/*
 * ajax.js | last modified 04/03/07
 * 
 * Requires:
 * 		XMLConverter.js
 * 		array.js
 * 		getelement.js
 * 		string.js
 */
	
	
	function Ajax(type, url, options) {

		this.type = type;
		this.url = url;
		this.options = options || {};
	}
	
	Ajax.prototype = {
		
		rObject: null,
		
		isUpdate: false,
		
		targets: null,
		
		options: {},
		
		defaultXHRHeader: 'XMLHTTPRequest',
		
		defaultPostHeader: 'application/x-www-form-urlencoded',
		
		useDefaultXHRHeader: true,
		
		useDefaultPostHeader: false,
		
		headers: {},
		
		updateInterval: null,
	 	
	 	/*
	 	 * Method: makeRequest
	 	 * 
		 * Intended PRIVATE
		 * @Parameters
		 *  none
	 	 * Make cross-browser compatible request
	 	 */
		makeRequest: function() {

			var funcArray = new FuncArray(
				function() {return new XMLHttpRequest()},
				function() {return new ActiveXObject('MSXML2.XMLHTTP')},
				function() {return new ActiveXObject('Microsoft.XMLHTTP')}
				);
			var rObject = funcArray.test();
			
			return rObject;
		},
		
		/*
		 * Method: getResponseObject
		 * 
		 * Intended PRIVATE
		 * @Parameters
		 *  none
		 */
		getResponseObject: function() {
			
			var rObject = null;
			try {
				var rObject = this.makeRequest();
			}
			catch(e) {}
			finally {
				return rObject;
			}
		},
		
		/*
		 * Method: applyHeaders
		 * 
		 * Intended PRIVATE
		 * @Parameters
		 *  none
		 * 
		 * Set all headers
		 */
		applyHeaders: function() {
			
			for(property in this.headers)
				this.rObject.setRequestHeader(property, this.headers[property]);
		},
		
		/*
		 * Method: handleReadyState
		 * 
		 * Intended PRIVATE
		 * @Parameters
		 *  REQUIRED (XMLHttpRequestObject) rObject
		 * 
		 * Handle success or failure of request and call appropriate user-defined
		 * functions if supplied
		 */
		handleReadyState: function(rObject) {

			var options = this.options;
			
			var requestStatus;

			if(rObject.status && rObject.status != 'undefined' && rObject.status != 0)
				requestStatus = rObject.status;
			else
				requestStatus = 130303;

			if(requestStatus >= 200 && requestStatus <= 300) {		
				if(this.update == true)
					this.doUpdate('success', rObject);

				if(options.onSuccess)
				    {
					options.params.push( rObject );
					options.onSuccess.apply( this, options.params );
				    }

			}
			else {
				if(options.onFailure)
					options.onFailure(rObject);
				if(this.update == true)
					this.doUpdate('failure', rObject);
			}
	
			this.restore();
			
		},
		
		/*
		 * Method: onStateChanged
		 * 
		 * Intended PRIVATE
		 * @Parameters
		 *  none
		 * 
		 * Method attached to onreadystatechanged property of the XMLHttpRequest object
		 * to call handleReadyState when ready state == 4
		 */
		onStateChange: function() {

			if(this.rObject.readyState == 4)
				this.handleReadyState(this.rObject);
		},

		/*
		 * Method: request
		 * 
		 * PUBLIC (but most often Ajax.update will be more appropriate than calling this method directly)
		 * @Parameters
		 *  none
		 * 
		 * - make a request and get the XMLHttpRequest object if it works
		 * - open the request and set headers 
		 * - wrap this class's onStateChange method and attach it to onreadystatechange property
		 * 	 of response object
		 */	
		request: function() {
			
			var options = this.options;
			
			var rObject = this.getResponseObject();
			this.rObject = rObject;
			
			if(rObject == null) {
				this.restore();
				return null;
			}

			rObject.open(this.type, this.url, true);

			if(this.useDefaultXHRHeader == true)
				this.setHeader('X-Requested-With', this.defaultXHRHeader, true)
				
			if(this.type == 'post' && this.useDefaultPostHeader == true)
				this.setHeader('Content-type', this.defaultPostHeader)
				
			if (rObject.overrideMimeType)
				this.setHeader('Connection', 'close');
				
			this.applyHeaders();

			var that = this;
			var readyStateResponse = function() {
				return that.onStateChange.apply(that);
			};
			
			rObject.onreadystatechange = readyStateResponse;
			rObject.send(null);

			return rObject;
		},
		
		/*
		 * Method: update
		 * 
		 * PUBLIC
		 * @Parameters
		 *  REQUIRED (object) target
		 *  OPTIONAL (int) frequency
		 * 	OPTIONAL (int) decay
		 * 
		 * - if frequency is set the user wants to update periodically so call setUpdateInterval
		 * - store target(s)
		 * - make request
		 * - if updating periodically, wrap timer method and pass to setTimeout with appropriate frequency
		 * 	 (+ decay)
		 */			
		update: function(target, frequency, decay) {
			
			if(typeof frequency != 'undefined')
				this.setUpdateInterval(frequency, decay);
			
			this.update = true;
			
			this.targets = {
				success: target? target.success ? $.id(target.success) : $.id(target) : null,
				failure: target? target.failure ? $.id(target.failure) : null : null
			}
			
			var response = this.request();

			if(this.updateInterval != null) {
				var that = this;
				setTimeout(function(){that.timer(target, frequency, decay)}, frequency * decay * 1000);
			}
			
			return response;				
		},
		
		/*
		 * Method: updateAtIntervals
		 * 
		 * PUBLIC 
		 * @Parameters
		 *  REQUIRED (object) target
		 *  OPTIONAL (int) frequency
		 * 	OPTIONAL (int) decay
		 */	
		updateAtIntervals: function(frequency, decay, target) {
			
			this.setUpdateInterval(frequency, decay);
			this.update(target, frequency, decay);
		},
		
		/*
		 * Method: timer
		 * 
		 * intended PRIVATE
		 * @Parameters
		 *  none
		 */	
		timer: function(target, frequency, decay) {
			new Ajax(this.type, this.url, this.options).update(target, frequency, decay);
		},
		
		/*
		 * Method: stopUpdates
		 * 
		 * PUBLIC
		 * @Parameters
		 *  none
		 * 
		 * - call this to stop periodical update
		 */		
		stopUpdates: function() {
			
			this.updateInterval == null;
		},
		
		/*
		 * Method: doUpdate
		 * 
		 * intended PRIVATE
		 * @Parameters
		 *  REQUIRED (string) result
		 *  REQUIRED (XMLHttpRequestObject) response
		 * 
		 * Update appropriate target element
		 */	
		doUpdate: function(result, response) {
				
			var target = (result == 'success')? this.targets.success: this.targets.failure;
			var response = response;

			var text = response.responseText.stripScripts();
			
			if(this.options.position) {
				var converter = new XMLConverter();
				var html = converter.toXHTML(response.responseXML);
				target.appendChild(html.firstChild);
			}
			else if(target != null)
				$.id(target).innerHTML = text;
			if(this.options.evalScripts == true)
				setTimeout(function() {response.responseText.evalScripts()}, 10);
		},
		
		/*
		 * Method: restore
		 * 
		 * intended PRIVATE
		 * @Parameters
		 *  none
		 * 
		 * Restore this object to original state
		 */	
		restore: function() {
			
			if(this.rObject) 
				this.rObject.onreadystatechange = function() {};
			
			this.rObject = null;
			this.isUpdate = false;
			this.targets = null;
			this.options = null;
		},
		
		/*
		 * Method: setHeader
		 * 
		 * PUBLIC (but most often only used internally)
		 * @Parameters
		 *  REQUIRED (string) title
		 *  REQUIRED (string) value
		 * 
		 * set the headers!
		 */	
		setHeader: function(title, value) {
			
			var headers = this.headers;
			
			if(!headers[title])
				headers[title] = value;
				
			else
				headers[title] += ',' + value;
			
		},

		/*
		 * Method: setDefaultXHRHeader
		 * 
		 * PUBLIC
		 * @Parameters
		 *  REQUIRED (bool) set
		 *
		 * allows user to chose not to use default XHR Header
		 */	
		setDefaultXHRHeader: function(set) {
			this.useDefaultXHRHeader = set;
		},

		/*
		 * Method: setDefaultPostHeader
		 * 
		 * PUBLIC
		 * @Parameters
		 *  REQUIRED (bool) set
		 *
		 * allows user to chose not to use default Post Header
		 */	
		setDefaultPostHeader: function(set) {
			this.useDefaultPostHeader = set;
		},

		/*
		 * Method: setUpdateInterval
		 * 
		 * PUBLIC
		 * @Parameters
		 *  REQUIRED (int) frequency
		 *  REQUIRED (int) decay
		 *
		 * allows user to chose not to use default Post Header
		 */	
		setUpdateInterval: function(frequency, decay) {
			this.updateInterval = {frequency: frequency, decay: decay || 1};
		}
			
	}

	/*
 * xmlconverter.js | last modified 04/03/07
 * 
 * Requires:
 * 		domutils.js
 * 		getelement.js
 */


	function XMLConverter() {
	}
	
	XMLConverter.prototype = {

		toXHTML: function(XML) {
			
			var childNodes = XML.childNodes;
			
			if(XML.nodeType == 3)
				return document.createTextNode(XML.nodeValue);
			else {
				try {
					var newNode = document.createElement(XML.nodeName);
					var attributes = XML.attributes;
					for(var i = 0; i < attributes.length; i++)
						DomUtils.setAnyAttribute(newNode, attributes[i].nodeName, attributes[i].nodeValue);
				}
				catch(e) {
					var newNode = document.createElement('HTML_DOCUMENT_FRAGMENT');
				}
			}
			for(var i = 0; i < childNodes.length; i++)
				newNode.appendChild(this.toXHTML(childNodes[i]));			
			
			return newNode;
		}
	}

	
	Inheritence.extend(String.prototype, { 
		
		/* Gets all numbers from a string and returns an array if more than one */
			
		parseInts: function() {
			var theArray = this.split(/\D+/g);
		
			/* Mozilla returns empty item if split occured at beginning or end of the string so must remove these if present */
			
			if(isNaN(parseInt(theArray[0]))) 
				theArray.shift();
			if(isNaN(parseInt(theArray[theArray.length-1]))) 
				theArray.pop();
				
			return (theArray.length == 1)? 
				theArray[0]: 
				theArray;
		},
			
		/* Removes hyphens from hyphenated words and makes following letter uppercase 
			looks for (hyphen)(letter)
			returns string with hyphens replaced with uppercase letter
			or orginal string if no hyphens */

		toFirstUpper: function() {
		
			var regEx = /(-)([a-z])/;
			var reArray;
			
			return (reArray = this.match(regEx))?
				this.replace(regEx, reArray[2].toUpperCase()):
				this;
		},
		
		stripScripts: function() {
			
			var RE_script = '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)';
			return this.replace(RE_script, '');
		},
		
		evalScripts: function() {
			
			var script = '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)';
			var regExp = new RegExp(script, 'img');
			var scripts = this.match(regExp) || [];
			for(var i = 0; i < scripts.length; i++)
				eval((scripts[i].match(script, 'im'))[1]);
		}
	});
	
	
	$ = function() {

		return {

		/* Accepts any number of arguments. Each can be an id or actual element object reference. Or will accept array of these. */

			id: function(element, toAdd) {

				if(typeof element == 'undefined')
					return;
					
				/* 
				Makes new array
				Checks to see if array has been passed and sets args variable accordingly
				*/
			
				var el = [];
				var args = (arguments[0] instanceof Array)? arguments[0]: [arguments[0]];

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

					/* Checks to see if argument is string and if not assumes object passed and simply adds it to the array */
			
					el[i] = (typeof args[i] == 'string')?
						document.getElementById(args[i]):
						args[i];

					if(toAdd)
						this._addFunctionality(el[i], toAdd);
						
				}	
			
				/* Returns only first item of the array if only one non-array argument was passed. Else returns array */
		
				return (args.length == 1)? el[0]: el;
			},

			attribute: function(method, string, parent, toAdd) {

				var els = ($.id(parent) || document).getElementsByTagName('*');
				var matched = new Array;
				var re = new RegExp("(^|\\s)" + string + "(\\s|$)");
	
				for (var i = 0, n = els.length; i < n; i++) {
					if (els[i][method].match(re)) {
						if(toAdd)
							this._addFunctionality(els[i], toAdd);
						matched.push(els[i])
					}
				}
			
				return matched;
			},

			className: function(className, parent) {
				
				return $.attribute('className', className, parent);
			},
			
			_addFunctionality: function(element, toAdd) {
	
				switch(toAdd) {
							
					case 'animation':
						if(!element.fade) element.fade = new Fade(element);
						break;
									
				}
			}

		}

	}();
			
	
	function Element(properties) {
		this.prop = properties;
		return this.build();
	}

	Element.prototype = {

		makingNew: true,
		prop: null,
		textNode: null,
    
		build: function() {
			if(this.prop.text)
				this.textNode = document.createTextNode(this.prop.text);
			if($.id(this.prop.id)) {
				this.makingNew = false;
				return;
			}  

			var newEl = document.createElement(this.prop.tag);
			for(property in this.prop) {
				if(property == 'className') 
					DomUtils.setAnyAttribute(newEl, property, 'class');
				if(property !== 'tag' && property !== 'text')
					DomUtils.setAnyAttribute(newEl, property, this.prop[property]);
			}
			if(this.textNode !== null)newEl.appendChild(this.textNode);
			
			return newEl;   
		}
	}

	ElementHandler = function() {
    	
		return { 
	
			_getEl: function(properties, update) {
				if(typeof el == 'undefined') var el = new Element(properties);
				if(el.makingNew == false && update !== true) {
					newEl = $.id(el.prop.id).cloneNode(true);
					$.id(el.prop.id).parentNode.removeChild($.id(el.prop.id));
					return newEl;		    
				}
				return el;
			},
	
			putBefore: function(destination, properties) {
				var newEl = this._getEl(properties);
				if(newEl.makingNew = false) this._getEl(properties);
				var parent = $.id(destination).parentNode;
				parent.insertBefore(newEl,$.id(destination));	       
			},
		
			putAfter: function(destination, properties) {
				var newEl = this._getEl(properties);
				if(newEl.makingNew = false) this._getEl(properties); //**** Test this ****/
				var parent = $.id(destination).parentNode;
				var destination = DomUtils.getNext(destination); //change
				parent.insertBefore(newEl,$.id(destination));
			},
		    
			putAtStart: function(parent, properties) {
				var newEl = this._getEl(properties);
				var destination = DomUtils.getChildren(parent)[0];
				$.id(parent).insertBefore(newEl,$.id(destination));
			},
			      
			putAtEnd: function(parent, properties) {
				var newEl = this._getEl(properties);
				$.id(parent).appendChild(newEl);
			},
		    
			replace: function(element, properties) {
				var newEl = this._getEl(properties);
				var parent = $.id(element).parentNode;
				var destination = $.id(element).nextSibling;
				$.id(element).parentNode.removeChild($.id(element));
				$.id(parent).insertBefore(newEl,$.id(destination));
			},
		    
			updateThis: function(element, properties) {
				var element = $.id(element);	    
				var newEl = this._getEl(properties, true);
				for (property in newEl.prop) {
					if (property !== 'style')
						element[property] = newEl.prop[property];
					else {
						var styles = newEl.prop.style.split(/;\s?/gi);
						for (var i = 0; i < styles.length; i++) {
							var stylePairs = styles[i].split(/:\s?/ig);
							element.style[stylePairs[0]] = stylePairs[1];
						}
					}
				}
				if (newEl.textNode !== null) 
				element.appendChild(newEl.textNode);
			},

			remove: function(element) {
				var element = $.id(element);
				if (element == null)
					return;
				var parent = element.parentNode;
				parent.removeChild(element);
			}
		}  
	}();

/* Constructor for CacheDivision objects, which can contain other CacheDivision objects. */

	function CacheDivision() {

		/* Create store for items that never need to be accessed directly by name, but only iterated though */
		this.plainStore = [];

		/* Create store for items which need to be accessed directly by name */
		this.linkedStore = {};

		/* Creates a new cache division and appends it to the owner object of this method, allowing a hierarchy of divisions */
		this.createDivision = function(name) {
			this[name] = new CacheDivision();
		};

		/* Adds an item to the plain (unlinked) store */
		this.add = function(value) {
			this.plainStore.push(value);
		};

		/* Iterates through all items in the unlinked store and calls the iterator (a function) passed to it.
		'iterator' can contain an 'item' parameter, which refers to each item being iterated */
		this.iterate = function(iterator) {
			for (var i = 0; i < this.plainStore.length; i++)
				iterator(this.plainStore[i]);
		};

		/* Adds an item to the linked store. The item then becomes accessible by its 'label' */
		this.addLinked = function(label, value) {
			this.linkedStore[label] = value;
		};
		
		/* Retrieves an item from the linked store */
		this.fetchLinked = function(label) {
			return this.linkedStore[label];
		};

		/* Iterates through all items in the linked store and calls the iterator (a function) passed to it.
		'iterator' can contain an 'item' and a 'value' parameter, which refer to each item and its value */
		this.iterateLinked = function(iterator) {
			for (property in this.linkedStore)
				iterator(this.linkedStore[property], value);
		};	

	}
    
	Cache = new CacheDivision();
	
	EventUtils = function() {
	
		return {

			unload: function() {

				if(Cache.listeners)
					Cache.listeners.iterate(function(item) {EventUtils.removeEventListener.apply(this,item)});
			},

			/**** Really need to test in Safari. Also maybe Safari has advanced handling for onclick so need to 
			detect this so can use it rather than the dodgy thing if type is click****/
			addEventListener: function(el,type,listener,capture) {

				if(!Cache.listeners)
					Cache.createDivision("listeners");
				
				if (typeof capture == 'undefined') 
					capture = false;

				var el = $.id(el);
				var l = el["_"+listener] = EventUtils.wrapListener(listener, el);

				if (el.addEventListener)
					el.addEventListener(type,listener,capture);

				else if (el.attachEvent)
					el.attachEvent('on'+type,l,capture);

				else { 
					try {
						el['on'+type] = wrappedL; 
					}
					catch(e) {}
				}

				Cache.listeners.add([el,type,listener,capture]);
			},
	
			removeEventListener: function(el,type,listener,capture) {

				if (typeof capture == 'undefined') 
					capture = false;
				
				var el = $.id(el);
				var l = el["_"+listener];

				if (el.removeEventListener) {
					el.removeEventListener(type,listener,capture);
				}
				
				else if (el.detachEvent) {
					el.detachEvent('on'+type,l,capture);
					l = null;
				}

				else {
					try {
						el['on'+type] = null; //For Safari. **** I guess this is right. Look it up ****
					}
					catch(e) {}
				}	
			},
	
			targetElement: function(e) {
							   
				var e = e || window.event;
				var target = e.target? e.target: e.srcElement;
				
				if (target.nodeType == 3)			    
					target = target.parentNode; //for Safari
				
				return target;
			},
	
			mouse: function(e) {
					   
				var e = e || window.event;
				
				x = e.pageX?
					e.pageX:
					e.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
				
				y = e.pageY?
					e.pageY:
					e.clientY + document.documentElement.scrollTop + document.body.scrollTop;
				
				return {x: x, y: y};
			},
		
			relTarget: function(e) {
						   
				var e = e || window.event;
				
				if (e.type == 'mouseover')
					return e.relatedTarget || e.fromElement;
				
				else if (e.type == 'mouseout')
					return e.relatedTarget || e.toElement;
			}, 

			//**** TEST ****/
			stopDefault: function(e) {
							 
				var e = e || window.event;
				
				if (e.preventDefault) {
					e.preventDefault;
					e.stopPropagation;
				}
				
				else {
					event.returnValue = false;
					event.cancelBubble = true;
				}
			},

			/* Detects when mouse truly leaves a layer. Ignores movement from inner layer to layer with mouseout attached
			which would normally trigger a mouseout event due to bubbling. Also ignores movement onto a link within the
			layer, which is normally registered as a mouseout. Call from within event listener: if (EventUtils.mouseLeave(e) == true)
			procede with listener. 
			*/
			mouseLeave: function(e) {
							
				var e = e || window.event;
				var target = this.targetElement(e);
				var rTarget = this.relTarget(e);

				while (rTarget != target && rTarget.nodeName != 'BODY')
					rTarget = rTarget.parentNode;

				return (rTarget == target)? false: true;  
			},

			wrapListener: function(method, scope) {
							  
				return function(e) {
					method.call(scope, e || window.event);
				}
			}

		}
	}();

	//To prevent IE memory leaks
	EventUtils.addEventListener(window, 'unload', EventUtils.unload);
	
	
	/*
	 * RenaissanceCMS
	 * fade.js | last modified 27-02-07
	 */
	
	/*
	 * Fade class, extends Animation.
	 */
	 
	/*
	 * Fade constructor function.
	 * @Parameters
	 * 	- REQUIRED element: element to be animated. Can also be an array of elements.
	 * 	- REQUIRED points: array [REQUIRED to, OPTIONAL from] - start point and end point for animation.
	 * 	- OPTIONAL duration: length of animation. Defaults to one second.
	 * 	- OPTIONAL options: object containing any properties/methods of the animation class, allowing custom 
	 * 						settings. Methods labled --CUSTOM-- are those you are most likely to want to set. 
	 */

	
	/*
	 * RenaissanceCMS
	 * animation.js | last modified 27-02-07
	 */
	
	/*
	 * Base Animation class
	 */
	 
	/*
	 * Animation constructor function.
	 * @Parameters
	 * 	- REQUIRED element: element to be animated. Can also be an array of elements.
	 * 	- REQUIRED attributes: can be single attribute or array of attributes.
	 *  - REQUIRED points: array [REQUIRED to, OPTIONAL from] - start point and end point for animation.
	 * 	- OPTIONAL duration: length of animation. Defaults to one second.
	 * 	- OPTIONAL options: object containing any properties/methods of the animation class, allowing custom 
	 * 						settings. Methods labled --CUSTOM-- are those you are most likely to want to set. 
	 */
	function Animation(element) {
	
		this.element = (typeof element == 'object')? element: $.id(element);
	}
	
	Animation.prototype = {
	
		/*
		 * Element or array of elements being animated. 
		 */
		element: null,
	
		/*
		 * Attribute or array of attributes being changed by animation.
		 */	 
		attribute: null,
		
		/*
		 * Duration of animation. Defaults to 1. This means 1 second unless timeUnits
		 * has been set to be other than seconds.
		 */
		duration: 1,
		
		/*
		 * Interval between animation frames.
		 */
		fps: 100,
		
		/*
		 * Units of time the duration of the animation is set in. Defaults to seconds.
		 */
		timeUnits: 1000,
		
		/*
		 * Array containing end and start points of the animation.
		 */
		points: [],
		
		/*
		 * Contains object passed in as optional parameter.
		 */
		options: {},
		
		/*
		 * Stores current value of attribute being changed.
		 */
		currentValue: 0,
		
		/*
		 * Used for determining whether attribute will be incremented or decremented.
		 */
		direction: 1,
		
		/* 
		 * PUBLIC
		 * @parameters
		 * 	- REQUIRED (int) step
		 * Set the interval between animation frames. 
		 */
		 
		isActive: true,
		
		/* 
		 * PUBLIC
		 * @Parameters
		 * 	- REQUIRED (int) units
		 * Set the units of time for the animation. 
		 */
		setTimeUnits: function(units) {
			
			this.timeUnits = units == 'miliseconds'? 1:
				units == 'seconds'? 1000:
				units == 'minutes'? 60000:
				360000;
		},
		
		setAttributes: function(attribute) {
		
			var atts = this.attribute;
			if(atts != null && typeof atts == 'string' && atts != attribute)
				this.attribute = [atts, attributes];
			else if(typeof atts == 'Object' && atts.indexOf(attribute) == -1)
				this.attribute.push(attribute);
			else if(atts == null)
				this.attribute = attribute;

				
		},		
		
		/*
		 * PUBLIC
		 * @Parameters
		 * 	- REQUIRED (int) to
		 *  - OPTIONAL (int) from
		 * Set end and start points for the animation.
		 */
		setPoints: function(points, attribute) {
			if(points.length == 1) {
				points[1] = (this.element._has_faded)?
					DomUtils.getStyle(this.element, attribute):
					0;
				this.element._has_faded = true;
			}
			this.points = points;
			if(points[1] > points[0]) {
				this.direction = -1;	
				this.highPoint = points[1];
				this.lowPoint = points[0];
				return;
			}
			else this.direction = 1;
			this.highPoint = points[0];
			this.lowPoint = points[1];		
		},
		
		/*
		 * PUBLIC but mostly for internal use
		 * @Parameters
		 * 	- REQUIRED (object) options
		 */
		setOptions: function(options) {
			
			this.options = options;
			
			for(property in options) {
				this[property] = options[property];
			}
			
		},
		
		/*
		 * Intended PRIVATE
		 * @Parameters
		 *  - see constructor function
		 * Called by contstructor to set properties for internal use
		 */
		initialise: function(attribute, points, duration, options) {
			
			this.setAttributes(attribute);
			
			if(typeof points == 'undefined')
				return;
			
			this.duration = duration || 1;
			this.setPoints(points, attribute);
			this.setOptions(options);
		},
		
		calculateValue: function(totalTime, totalDistance, fps, current) {
			
			var value = ((totalTime * totalDistance) / fps);
				return (this.direction == 1)? value + current: current - value;
		},
		
		deactivate: function() {
			this.isActive = false;
		},
		
		activate: function() {
			this.isActive = true;
		},
		
		/*
		 * PUBLIC
		 * Starts the animation.
		 */
		start: function(attribute, points, duration, options) {
	
			if(this.isActive == false)
				return;
			
			clearInterval(this.animThread);
	
			this.initialise(attribute, points, duration, options);
	
			this.doAnimation(this.element, this.points);
			this._onStart(this.element);
		},
		
		/*
		 * Intended PRIVATE
		 * Defines onNewFrame function which is called for each frame of the animation.
		 */

		doAnimation: function(element, points) {
			
			var duration = this.duration = 1 / this.duration;
			var totalFrames = duration * this.fps;
			var dir = this.direction;
			var totalDistance = (dir == 1)? points[0] - points[1]: points[1] - points[0];
			var interval = duration * this.timeUnits / totalFrames;
			var att = this.attribute;
			var value = points[1];

			this.animThread = setInterval(onNewFrame, interval);
			var that = this;
			function onNewFrame() {
				value = that.calculateValue(that.duration, totalDistance, that.fps, value);
				if((dir == 1 && value >= that.points[0]) || (dir == -1 && value <= that.points[0])) {
					clearInterval(that.animThread);
					if(that.points[0] == 1)
						DomUtils.setStyle(that.element, att, 0.99999999);
					else if(that.points[0] == 0)
						DomUtils.setStyle(that.element, att, 0);
					that._onFinish(that.element);
					return;
				}	
				DomUtils.setStyle(that.element, att, value);
			}	
		},
		
		_onStart: function(element) {
			this.onStart();
		},
		
		_onFinish: function() {
		},
		
		/*
		 * --CUSTOM METHOD--
		 * Intended PRIVATE
		 * Called at start of animation. 
		 */
		onStart: function() {
		},
	
		/*
		 * --CUSTOM METHOD--
		 * Intended PRIVATE
		 * Called for each animation frame - be cautious with it so as not to affect performance! 
		 */
		onChange: function() {
		},
		
		/*
		 * --CUSTOM METHOD--
		 * Intended PRIVATE
		 * Called at end of animation. 
		 */
		onFinish: function(element) {
			this.onFinish();
		},
		
		/*
		 * --CUSTOM METHOD--
		 * Intended PRIVATE
		 * Called at start of animation. 
		 */
		atTime: function() {
		/*
		 * Body of this function should contain only a setTimeout function containing a function 
		 * for execution part way through the animation.
		 */
		}
		
	}
	 
	 function Fade(element) {

		this.element = (typeof element == 'object')? element: $.id(element);
	 }
	 
	 Inheritence.extend(Fade.prototype, Animation.prototype);
	 
	 Inheritence.extend(Fade.prototype, {
	 	
	 	start: function(points, duration, options) {
		 	if(this.isActive == false)
				return;

	 		clearInterval(this.animThread);
	 		
	 		if(arguments.length != 0)
		 		this.initialise('opacity', points, duration, options);

			this.doAnimation(this.element, this.points);
			
			this._onStart(this.element);
	 	},
		
	 	/*
	 	 * @Overrides base
		 * intended PRIVATE
	 	 */
		_onStart: function(element) {
			if(this.direction !== 1)
				return;
			if(this.visibility == true) {
				DomUtils.setStyle(element, 'opacity', this.points[1]);
				element.style.visibility = 'visible';
			}
			if(this.display == true) {
				DomUtils.setStyle(element, 'opacity', this.points[1]);
				element.style.display = 'block';
			}
		},
		
		_onFinish: function(element) {
			if(this.direction == 1) {
				if(this.focus == true)
				element.focus();
				return;
			}
			if(this.visibility == true)
				element.style.visibility = 'hidden';
			if(this.display == true)
				element.style.display = 'none';
		}
	 	
	 });
	 
var menus={};

function add_image_overlays(){

	var imgs=$.id('main-content').getElementsByTagName('IMG');
	var b=document.getElementsByTagName('BODY');
	b=b[0];

	for(var i=0;i<imgs.length;i++)
		{
		var c=DomUtils.getAnyAttribute(imgs[i],'class');
		if(c!=null && c.indexOf('property-image')>-1)
			{
			var off=DomUtils.getTrueOffset(imgs[i]);
			
			var top=(off.t+imgs[i].offsetHeight)-38;
			var left=(off.l+imgs[i].offsetWidth)-28;

			ElementHandler.putAtEnd(
								b,
								{
								tag: 'IMG',
								src: 'http://www.tropicalconnections.co.uk/grfx/palm-tree-small.png',
								className: 'overlay',
								title: 'Tropical Connections',
								alt: 'Tropical Connections -- Propertyies for sale in Barbados',
								style: 'top:'+top+'px; left:'+left+'px;'
								}
								);
			}
		}
}

function show_hide_menu_m(){

	var obj=$.id(this._p);

	if(typeof obj._timeout!=undefined && obj._timeout!=false)
		{
		clearTimeout(obj._timeout);
		obj._timeout=false;
		}
	else
		obj._timeout=setTimeout('show_hide_menu("'+obj.id+'",true)',800);
}

function show_hide_menu(obj,now){

	//menus is meant to be global

	if(this.id)
		obj=this;
	else
		obj=$.id(obj);

	var menu_id=obj.innerHTML.replace(/ /g,'-')+'_top';
	menu_id=menu_id.toLowerCase();
	
	if(menu_id.indexOf('menu-')==-1)
		menu_id='menu-'+menu_id;

	if(now!=true)
		{
		for(layerId in menus)
			if(menus[layerId]!=obj.id)
				show_hide_menu(layerId,true);

		if($.id(menu_id))
			{
			if(!menus[obj.id])
				{
				menus[obj.id]=obj.id;
				$.id(menu_id)._p=obj.id;
			
				$.id(menu_id).style.left=(obj.offsetLeft+45)+'px';

				clearTimeout(obj._timeout);
			
				fader(menu_id,2.25,100,0,1);
				}
			else
				obj._timeout=setTimeout('show_hide_menu("'+obj.id+'",true)',800);				
			}
		}
	else
		{
		delete menus[obj.id];
		clearTimeout(obj._timeout);
		fader(menu_id,-2.25,0,100,1);
		}
}

function add_sub_menus(){

	var target=$.id('sub-menu-target');
	var menus=$.className('sub-menu','text-admin-text');

	for(var i=0;i<menus.length;i++)
		{
		var menu=menus[i].cloneNode(true);

		menu.id=menu.id+'_top';

		target.appendChild(menu);

		menu.removeChild(menu.getElementsByTagName('H2')[0]);
		$.id('text-admin-text').removeChild(menus[i]);
		}

	var main_menu_items=$.id('menu-main-menu').getElementsByTagName('A');

	for(i=0;i<(main_menu_items.length);i++)
		{
		EventUtils.addEventListener(main_menu_items[i],'mouseover',show_hide_menu);
		EventUtils.addEventListener(main_menu_items[i],'mouseout',show_hide_menu);

		var menu=main_menu_items[i].innerHTML.replace(/ /g,'-')+'_top';
		menu='menu-'+menu.toLowerCase();

		if($.id(menu))
			{
			EventUtils.addEventListener(menu,'mouseover',show_hide_menu_m);
			EventUtils.addEventListener(menu,'mouseout',show_hide_menu_m);
			}
		}
}

function deal_with_pngs(){

	if(BrowserDetect.browser=='Explorer' && BrowserDetect.version==6)
		{
		var imgs=document.getElementsByTagName('IMG');

		for(var i=0;i<imgs.length;i++)
			{
			var img=imgs[i];

			if(img.src.indexOf('.png')>-1)
				{			
				var cur=img.src;

				img.src='http://www.tropicalconnections.co.uk/grfx/s.gif';
				
				if(img.style.filter=='')
					img.style.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+cur+'")';
				}
			}			
		}
}

function add_roll(obj,text,heights,add_fade,add_link,set_cookie,start_hidden){

	obj=$.id(obj);

	var contents=obj.innerHTML;

	var children=DomUtils.getChildren(obj);
	var c=DomUtils.getAnyAttribute(children[0],'class');

	if(c=='inner')
		var inner=children[0];
	else
		{
		contents='<div id="'+obj.id+'-inner" class="inner">'+contents+'</div>';
		obj.innerHTML=contents;
		var inner=$.id(obj.id+'-inner');
		}

	obj._add_link=add_link;
	obj._text=text;

	var off_height=(typeof heights[2]!='undefined')?inner.offsetHeight+heights[2]:inner.offsetHeight;

	obj._natural_height=(heights[0]=='full')?off_height:heights[0];
	obj._hidden_height=heights[1];

	obj._set_cookie=set_cookie;
	obj._has_fade=add_fade;

	obj._hidden=start_hidden;

	var text=(obj._hidden)?text[0]:text[1];
	var fade_display=(obj._hidden)?'block':'none';
	
	var show_hide=(add_link)?'<a id="'+obj.id+'-show-hide-link" href="javascript:roll(\''+obj.id+'\')" class="show-hide" onclick="this.blur()">'+text+'</a>':'';

	var	fade=(add_fade)?'<div style="display:'+fade_display+'"><img id="'+obj.id+'-fade" src="http://www.tropicalconnections.co.uk/grfx/fade.png" class="show-hide-fade" alt="graphic element" title="" /></div>':'';
	
	contents+=show_hide+fade;

	obj.innerHTML=contents;

	if(obj._hidden)
		DomUtils.addClassName(obj.id+'-show-hide-link','on');
	else
		DomUtils.addClassName(obj.id+'-show-hide-link','off');

	if(obj._set_cookie)
		{
		var state=readCookie('roll-'+obj.id);

		if(state=='hidden')
			roll(obj);
		}
}

function roll(obj){

	obj=$.id(obj);

	if(typeof obj._hidden==null)
		obj._hidden=false;

	if(obj._hidden)
		{
		changeDim(obj.id,3,obj._natural_height,8,'px','visible');

		if(obj._add_link)
			{
			$.id(obj.id+'-show-hide-link').innerHTML=obj._text[1];

			DomUtils.removeClassName(obj.id+'-show-hide-link','on');
			DomUtils.addClassName(obj.id+'-show-hide-link','off');
			}

		if(obj._set_cookie)
			eraseCookie('roll-'+obj.id);

		if(obj._has_fade)
			$.id(obj.id+'-fade').style.display='none';

		obj._hidden=false;
		}
	else
		{
		obj._natural_height=obj.offsetHeight;

		obj.style.overflow='hidden';
		changeDim(obj.id,3,obj._hidden_height,8,'px','hidden');

		if(obj._add_link)
			{
			$.id(obj.id+'-show-hide-link').innerHTML=obj._text[0];

			DomUtils.removeClassName(obj.id+'-show-hide-link','off');
			DomUtils.addClassName(obj.id+'-show-hide-link','on');
			}

		if(obj._set_cookie)
			createCookie('roll-'+obj.id,'hidden',60);

		if(obj._has_fade)
			$.id(obj.id+'-fade').style.display='block';
		
		obj._hidden=true;
		}
}

function add_side_formatting(){
	
	var boxes=DomUtils.getChildren('side-boxes');

	for(var i=0;i<boxes.length;i++)
		{
		var box=boxes[i];
		
		if(box.id.indexOf('images')==-1)
			{
			DomUtils.addClassName(box,'box');

			var content=box.innerHTML;
			content='<div id="side-box-'+i+'-inner" class="inner">'+content+'</div>';
			
			content+='<div id="side-box-'+i+'-background" class="background"></div>';
			content+='<img src="http://www.tropicalconnections.co.uk/grfx/side-box-tl.png" class="corner" style="position: absolute; top:0px; left:0px" alt="graphic element" title="" />';
			content+='<img src="http://www.tropicalconnections.co.uk/grfx/side-box-br.png" class="corner" style="position: absolute; bottom:0px; right:0px" alt="graphic element" title="" />';
		
			box.innerHTML=content;

			if(BrowserDetect.browser=='Explorer' && BrowserDetect.version==6)
				{
				$.id('side-box-'+i+'-background').style.height=$.id('side-box-'+i+'-inner').offsetHeight+4;
				
				if(box.tagName=='FORM')
					{
					var w=$.id('side-box-'+i+'-background').offsetWidth;
					$.id('side-box-'+i+'-background').style.width=(w+4)+'px';
					var h=31;
					}
				else
					var h=35;
				}
			else
				var h=36;
		
			add_roll(box,['',''],['full',h],false,true,true,false);
			}
		}
}

function deal_with_search_form(){
/*
	var results=$.className('results');
	var no_results=$.className('no_results');

	if(results && !no_results)
		{
		var c=DomUtils.getChildren(results);
	
		if(c.length)
			{
			var form=$.id('Property-Search-Form');
	
			if(!form)
				form=$.id('Advanced-Property-Search-Form');
	
			form.style.height='15px';
			form.style.overflow='hidden';
	
			add_roll(form,['Show search form.','Hide search form.'],['full',15],false,true,false,true);
			}
		}*/
}

function deal_with_island_form(){

	var b=document.getElementsByTagName('BODY');
	b=b[0];

	var c=DomUtils.getAnyAttribute(b,'class');

	if(c.indexOf('island-description')>-1)
		{
		var form=$.id('form-island-enquiry-form');

		if(form)
			{

			var target=$.className('island-description');
	
			for(var i=0;i<target.length;i++)
				if(target[i].tagName=='DIV')
					{
					target=target[i];
					break;
					}
	
			ElementHandler.remove(form);
			target.parentNode.insertBefore(form,target);

			c=DomUtils.getAnyAttribute(form,'class');
	
			if(c.indexOf('intro')>-1)
				{
				form.style.height='15px';
				form.style.overflow='hidden';
		
				add_roll(form,['Click to enquire about property and services for this island','Hide form'],['full',15],false,true,false,true);
				}
			else
				{
				add_roll(form,['Click to enquire about property and services for this island','Hide form'],['full',15],false,true,false,false);
				}
			}
		}
}

function deal_with_property_form(form,property){

	var children=DomUtils.getChildren(property);

	for(var i=0;i<children.length;i++)
		{
		var c=DomUtils.getAnyAttribute(children[i],'class');
		if(c=='description')
			break;
		}

//	ElementHandler.remove(form);
//	property.insertBefore(form,children[1]);

	var c=DomUtils.getAnyAttribute(form,'class');

	if(c.indexOf('intro')>-1)
		{
		form.style.height='15px';
		form.style.overflow='hidden';

		add_roll(form,['Click to enquire about this property','Hide form'],['full',15],false,true,false,true);
		}
	else
		{
		add_roll(form,['Click to enquire about this property','Hide form'],['full',15],false,true,false,false);
		}
}

function deal_with_property(){

	var bod=document.getElementsByTagName('BODY');
	bod=bod[0];

	var property_found=false;

	if(bod.id.indexOf('page-property')==0)
		var properties=$.className('property');
	else
		var properties=false;

	if(properties!=false)
		{
		for(var i=0;i<properties.length;i++)
			{
			var property=properties[i];
			if(property.parentNode.id=='main-content')
				{
				property_found=true;
				break;
				}
			}
		}

	if(property_found)
		{
		/*
		var children=DomUtils.getChildren(property);

		for(var j=0;j<children.length;j++)
			{
			var child=children[j];
			var c=DomUtils.getAnyAttribute(child,'class');

			if(c=='description')
				{
				var h=child.offsetHeight;
				if(h>200)
					{
					child.style.height='200px';
					child.style.overflow='hidden';

					add_roll(child,['Read more','Hide description'],['full',200,15],true,true,false,true);
					}
				}
			}
		*/
		var items=$.id('main-content').getElementsByTagName('FORM');

		deal_with_property_form(items[0],property)
		}
}

function setup(){
	
	if(DomUtils.getViewXY().x<850)
		{
		$.id('main-content').style.marginLeft='4px';

		$.id('side-boxes').style.width='185px';
		$.id('side-boxes').style.marginTop='120px';
		$.id('side-boxes').style.marginLeft='5px';
		}

	add_sub_menus();
	add_side_formatting();
	deal_with_property();
	deal_with_island_form();
//	add_image_overlays();
	deal_with_pngs();
}

var dimensions=new Array('top','left','width','height','marginLeft','marginTop');

function animLS(lyr,dim,target,step,mode,overflow){

	obj=document.getElementById(lyr);

	real=obj.lsReal[dim];
	delta=Math.sqrt(Math.abs(target-real))*0.0125;

	step=obj.sig[dim]*10;

	new_dim=obj.lsReal[dim];
	obj.lsReal[dim]=real+(obj.step[dim]*step*delta);

	var d=dimensions[dim];

	if((new_dim>=target && obj.sig[dim]>0) || (new_dim<=target && obj.sig[dim]<0))
		{
		target=target+''+mode;
		obj.style[d]=target;
		clearInterval(obj.lsInterval[dim]);
		obj.lsInterval[dim]=0;

		if(overflow!='off')
			obj.style.overflow=overflow;
		return;
		}
	else
		{
		new_dim=new_dim+''+mode;
		obj.style[d]=new_dim;
		}
}

function changeDim(lyr,dim,target,step,mode,overflow){

	obj=$.id(lyr);

	if(obj.lsReal==null)
		{
		w_w=document.body.clientWidth;
		w_h=document.body.clientHeight;

		obj.step=new Array();
		obj.sig=new Array();
		obj.lsReal=new Array();
		obj.lsInterval=new Array();
		}

	if(obj.lsInterval[dim]!=0)
		{
		clearInterval(obj.lsInterval[dim]);
		obj.lsInterval[dim]=0;
		}

	switch(dim)
		{
		case 0:
			obj.lsReal[0]=(!parseInt(obj.offsetTop))?0:parseInt(obj.offsetTop);
			break;
		case 1:
			obj.lsReal[1]=(mode=='%')?((parseInt(obj.offsetLeft)/w_w)*100):parseInt(obj.offsetLeft);
			break;
		case 2:
			obj.lsReal[2]=(mode=='%')?((parseInt(obj.offsetWidth)/w_w)*100):parseInt(obj.offsetWidth);
			break;
		case 3:
			obj.lsReal[3]=(mode=='%')?((parseInt(obj.offsetHeight)/w_h)*100):parseInt(obj.offsetHeight);
			break;
		case 4:
			obj.lsReal[4]=parseInt(obj.style.marginLeft);
			break;
		case 5:
			obj.lsReal[5]=(!parseInt(obj.style.marginTop))?0:parseInt(obj.style.marginTop);
			break;
		}

	obj.step[dim]=step;
	obj.sig[dim]=((target-obj.lsReal[dim])>0)?1:-1;

	obj.lsInterval[dim]=setInterval("animLS('"+lyr+"',"+dim+","+target+","+step+",'"+mode+"','"+overflow+"')",30);
}

function createCookie(name,value,days) {

	if(days)
		{
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
		}
	else
		var expires = "";

	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {

	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name){
	createCookie(name,"null",-1);
}

function fade(obj,d,target,f){

	lyr=document.getElementById(obj);
	lyr.fade+=(d*20);

	if((d>0 && lyr.fade>=target) || (d<0 && lyr.fade<=target))
		{
		if(target>99)
			lyr.style.filter='';

		//lyr.fade=target*0.9999999;
		clearInterval(lyr.fade_on);
		lyr.fade_on=0;
		if(f==1 && d>0)
			{
			lyr.style.display='block';
			}
		}

	if(f>0)
		{
		if(lyr.fade<=0)
			lyr.style.display='none';
		else
			lyr.style.display='block';
		}

	lyr.style.opacity=lyr.fade/100;
	lyr.style.filter="progid:DXImageTransform.Microsoft.Alpha(Opacity="+lyr.fade+")";
}

function fader(lyr,d,target,init,f){
	obj=$.id(lyr);
	
	if(obj.fade_on==null)
		{			
		obj.fade_on=0;
		obj.fade=init;
		}

	if(obj.fade_on!=0)
		{
		clearInterval(obj.fade_on);
		obj.fade_on=0;
		}

	obj.fade_on=setInterval("fade('"+lyr+"',"+(d/2)+","+target+","+f+")",50);
}

var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};

BrowserDetect.init();

function nospam(a,b,c){
	if(!c)
		c='web site enquiry';

	window.location='mailto:'+b+'@'+a+'?subject='+c;
}

function form_submit(frm){
	$.id(frm).submit();
}

