/* Bent Live: cached v:1.21.16 */ 
var un = undefined, undef = undefined;

var jj = {

	
	bind: function (object, func) {
		if (arguments.length > 2) {
			var args = jj.argsSlice (arguments, 2);
			if (typeof (func) == 'string') {
				return function () {
					return object [func].apply (object, jj.join (args, jj.argsSlice (arguments)));
				};
			} else {
				return function () {
					return func.apply (object, jj.join (args, jj.argsSlice (arguments)));
				};
			}
		} else {
			if (typeof (func) == 'string') {
				return function () {
					return object [func].apply (object, arguments);
				};
			} else {
				return function () {
					return func.apply (object, arguments);
				};
			}
		}
	},

	
	utfLen: function (data) {
		var ret = 0;
		for (var i = 0; i < data.length; i++) {
			var c = data.charCodeAt (i);
			if (c < 0x80) ret += 1;
			else if (c < 0x800) ret += 2;
			else if (c < 0x10000) ret += 3;
			else if (c < 0x200000) ret += 4;
			else if (c < 0x4000000) ret += 5;
			else ret += 6;
		}
		return ret;
	},

	
	errorSummary: function (error) {
		switch (typeof error) {
		case 'string':
			return error;
		case 'object':
			if ('fileName' in error)
				return error.fileName + ':' + error.lineNumber + ' ' + 
					error.message + ' (' + error.name + ')';
			else return error.message;
		default:
			return jj.pretty (error);
		}
	},

		
	leadingZero: function (value) {
		return String(value).length < 2 ? '0'+value : String(value);
	},
		
	returnNumeric: function (input) {
		return input.replace(/[^0-9]+/g,'');
	},

	min: function () {
		var value = undefined;
		for (var i = 0; i < arguments.length; i++)
			if (value == undefined || value > arguments [i])
				value = arguments [i];
		return value;
	},

	max: function () {
		var value = undefined;
		for (var i = 0; i < arguments.length; i++)
			if (value == undefined || value < arguments [i])
				value = arguments [i];
		return value;
	},

	
	def: function () {
		var name = arguments [0];
		var props = arguments [arguments.length - 1];

		
		if (! (name in props))
			throw 'Constructor not found: ' + name;

		
		var classObj = {
			name: name,
			props: props
		};

		
		var ret = function () {
			this [name].apply (this, arguments);
		};
		ret.name = name;

		
		ret.prototype.__class = classObj;

		
		jj.mergeIntoNew (ret.prototype, props);

		
		for (var i = arguments.length - 2; i >= 1; i--)
			jj.mergeIntoNew (ret.prototype, arguments [i].prototype);

		
		return ret;
	},

	

	merge: function () {
		var dest = {};
		for (var i = 0; i < arguments.length; i++) {
			jj.mergeInto (dest, arguments [i]);
		}
		return dest;
	},

	
	mergeInto: function () {
		var dest = arguments [0];
		for (var i = 1; i < arguments.length; i++) {
			var src = arguments [i];
			for (var key in src)
				dest [key] = src [key];
		}
		return dest;
	},

	
	mergeIntoReal: function (dest, srcs) {
		for (var i = 0; i < srcs.length; i++) {
			var src = srcs [i];
			for (var key in src)
				dest [key] = src [key];
		}
	},

	
	mergeIntoNew: function () {
		var dest = arguments [0];
		for (var i = 1; i < arguments.length; i++) {
			var src = arguments [i];
			for (var key in src) {
				if (! (key in dest))
					dest [key] = src [key];
			}
		}
	},

	
	mergeIntoNewReal: function (dest, srcs) {
		for (var i = 0; i < srcs.length; i++) {
			var src = srcs [i];
			for (var key in src) {
				if (! (key in dest))
					dest [key] = src [key];
			}
		}
	},

	
	callSummary: function (name, args) {
		var s = name + ' (';
		if (jj.isArray (args) || jj.isArguments (args)) {
			var first = true;
			for (var i = 0; i < args.length; i++) {
				if (! first) s += ', ';
				s += jj.pretty (args [i]);
				first = false;
			}
		} else if (jj.isMap (args)) {
			var first = true;
			for (var i in args) {
				if (! first) s += ', ';
				s += i + ': ' + jj.pretty (args [i]);
				first = false;
			}
		} else if (args == undefined) {
			s += 'undefined';
		} else {
			s += '?' + jj.pretty (args) + '?';
		}
		return s + ')';
	},

	
	handle: function (handlerAny, funcName, args) {
		switch (typeof (handler)) {

		case 'function':
			return handlerAny (funcName, args);

		case 'object':
			return handerAny [funcName].apply (handlerAny, jj.isArray (args)? args : [ args ]);

		default:
			throw 'Eek';
		}
	},

	handlerFunc: function (handlerAny, errorIfNotFound, prefix) {

		if (jj.isUndefined (errorIfNotFound))
			errorIfNotFound = true;

		if (jj.isUndefined (prefix))
			prefix = '';

		switch (typeof (handlerAny)) {

		case 'function':
			return handlerAny;

		case 'object':
			var rest = jj.argsSlice (arguments, 3);
			return function (name, args) {

				
				if (prefix + 'before' in handlerAny) {
					handlerAny [prefix + 'before'].apply (handlerAny, jj.join (rest, [ name, args ]));
				}

				var retVal;
				if (prefix + name in handlerAny) {

					
					if (jj.isArray (args)) {
						retVal = handlerAny [prefix + name].apply (handlerAny, args);
					} else if (jj.isMap (args)) {
						var fn = handlerAny [prefix + name];
						if (fn.length == 0) {
							retVal = fn.apply (handlerAny, jj.join (rest, [ ]));
						} else if (fn.length == 1) {
							retVal = fn.apply (handlerAny, jj.join (rest, [ args ]));
						} else if (fn.length == 2) {
							retVal = fn.apply (handlerAny, jj.join (rest, [ name, args ]));
						}
					} else {
						retVal = handlerAny [prefix + name].apply (handlerAny, rest);
					}

				} else if (prefix + 'any' in handlerAny) {

					
					return handlerAny [prefix + 'any'].apply (handlerAny, jj.join (rest, [ name, args ]));

				} else if (errorIfNotFound) {

					
					throw 'No handler for ' + name;
				}

				
				if (prefix + 'after' in handlerAny) {
					handlerAny [prefix + 'after'].apply (handlerAny, jj.join (rest, [ name, args ]));
				}

				return retVal;
			};

		case 'undefined':
			return function (name, args) {
			};

		default:
			throw 'Eek ' + typeof (handlerAny);
		}
	},
	
	
	handlerFuncSpecial: function (mainObject, childObject) {
		return function (name, args) {
			if (! (name in childObject))
				throw 'No handler for ' + name;
			return childObject [name].apply (mainObject, args);
		};
	},

	
	copy: function (data) {

		if (data == undefined) {
			return undefined;
		}

		if (typeof data == 'null') {
			return data;
		}

		if (typeof data == 'number') {
			return data;
		}

		if (typeof data == 'string') {
			return data;
		}

		if (jj.isArray (data)) {
			var ret = [];
			for (var i in data)
				ret.push (jj.copy (data [i]));
			return ret;
		}

		if (jj.isMap (data)) {
			var ret = {};
			for (var i in data)
				ret [i] = data [i];
			return ret;
		}

		if (typeof data == 'boolean') {
			return data;
		}

		throw 'Trying to copy ' + data;
	},

	eq: function () {

		if (arguments.length < 1)
			throw new Exception ('Not enough arguments for jj.eq');

		for (var i = 1; i < arguments.length; i++) {
			if (! jj.eqReal (arguments [0], arguments [i])) {
				return false;
			}
		}

		return true;
	},

	eqReal: function (left, right) {

		if (left == null)
			return right == null;

		if (typeof left == 'undefined')
			return typeof right == 'undefined';

		if (typeof left == 'number')
			return typeof right == 'number' && left == right;

		if (typeof left == 'boolean')
			return typeof right == 'boolean' && left == right;

		if (typeof left == 'string')
			return typeof right == 'string' && left == right;

		if (typeof left == 'object' && left instanceof Array)
			return typeof right == 'object' && right instanceof Array && jj.eqArray (left, right);

		if (jj.isMap (left))
			return jj.isMap (right) && jj.eqMap (left, right);

		throw 'Don\'t know how to handle ' + typeof left;
	},

	eqMap: function (left, right) {

		
		for (var i in left) {
			if (! (i in right))
				return false;
			if (! jj.eqReal (left [i], right [i]))
				return false;
		}

		
		for (var i in right) {
			if (! (i in left))
				return false;
		}

		
		return true;
	},

	eqArray: function (left, right) {

		if (left.length != right.length)
			return false;

		for (var i in left) {
			if (! jj.eqReal (left [i], right [i]))
				return false;
		}
		
		return true;
	},

	propNameRegexp: /^[a-zA-z_][a-zA-Z0-9_]*$/,

	
	pretty: function (data) {

		if (data == undefined) {
			return 'undefined';
		}

		if (typeof data == 'number') {
			return '' + data;
		}

		if (typeof data == 'string') {
			return '\'' + data
				.replace (/\u005c/g, '\\\\')
				.replace (/\u0027/g, '\\\'')
				.replace (/\u0000/g, '\\u0000')
				.replace (/\u0008/g, '\\b')
				.replace (/\u0009/g, '\\t')
				.replace (/\u000a/g, '\\n')
				.replace (/\u000b/g, '\\v')
				.replace (/\u000c/g, '\\f')
				.replace (/\u000d/g, '\\r')
				+ '\'';
		}

		if (typeof data == 'array' || data.constructor == Array) {
			s = '[ ';
			var first = true;
			for (var i = 0; i < data.length; i++) {
				if (! first) s += ', ';
				s += jj.pretty (data [i]);
				first = false;
			}
			return s + ' ]';
		}

		if (typeof data == 'object') {
			var s = '{ ';
			var first = true;
			for (var key in data) {
				if (! first) s += ', ';
				s += (jj.propNameRegexp.test (key)? key : jj.pretty (key))
					+ ': ' + jj.pretty (data [key]);
				first = false;
			}
			return s + ' }';
		}

		if (typeof data == 'boolean') {
			return data? 'true' : 'false';
		}

		if (typeof data == 'function') {
			return 'function(...){...}';
		}

		throw 'Trying to encode ' + data;
	},

	inx: function (left ) {
		for (var i = 1; i < arguments.length; i++) {
			if (left == arguments [i])
				return true;
		}
		return false;
	},

	arrayToSet: function (array) {
		var ret = {};
		for (var i = 0; i < array.length; i++)
			ret [array [i]] = true;
		return ret;
	},

	setToArray: function (set) {
		var ret = [];
		for (var key in set)
			ret.push (key);
		return ret;
	},
	objectToArray: function (obj) {
		var ret = [];
		for (var key in obj)
			ret.push (obj[key]);
		return ret;
	},

	map: function () {
		var ret = {};
		for (var i = 0; i < arguments.length; i += 2) {
			ret [arguments [i]] = arguments [i + 1];
		}
		return ret;
	},

	mapKeys: function (map) {
		var ret = [];
		for (var key in map)
			ret.push (key);
		return ret;
	},

	mapNumberKeys: function (map) {
		var ret = [];
		for (var key in map)
			ret.push (Number (key));
		return ret;
	},

	numberSetToArray: function (set) {
		var ret = [];
		for (var i in set)
			ret.push (Number (i));
		return ret;
	},

	stringSetToArray: function (set) {
		var ret = [];
		for (var i in set)
			ret.push (String (i));
		return ret;
	},

	mapValues: function (map) {
		var ret = [];
		for (var i in map)
			ret.push (map [i]);
		return ret;
	},
	
	randomArray: function (in_array, in_len) {
		var ret = [];
		var present = [];
		for (var i= 0; i<in_len; i++){
			var random = Math.floor (in_array.length * Math.random ());
			if(!this.inArray(random,present)){
				present.push(random);
				ret.push (in_array[random]);
			}
		}
		return ret;
	},
	
	ArrayAminusB: function (in_a, in_b) {
	var ret = [];
	var newValue = false;
	for(var i = 0 ; i<in_a.length; i++){
		if((!this.inArray(in_a[i],in_b))){
			ret.push(in_a[i]);
		}
	}
	return ret;
	},
	
	isArray: function (any) {
		if (typeof any != 'object') return false;
		if (! (any instanceof Array)) return false;
		return true;
	},

	isMap: function (object) {
		if (typeof object != 'object') return false;
		if (object == null) return false;
		if (object.constructor != Object && object instanceof object.constructor) return false;
		return true;
	},

	isRegExp: function (any) {
		if (typeof any != 'function') return false;
		if (any.constructor != RegExp) return false;
		return true;
	},

	isString: function (any) {
		return typeof any == 'string';
	},

	isInt: function (any) {
		return typeof any == 'number' && Math.floor (any) == any;
	},

	isIntArray: function (any) {
		if (! jj.isArray (any)) return false;
		for (var i = 0; i < any.length; i++) {
			if (! jj.isInt (any [i])) return false;
		}
		return true;
	},

	isStringArray: function (any) {
		if (! jj.isArray (any)) return false;
		for (var i = 0; i < any.length; i++) {
			if (! jj.isString (any [i])) return false;
		}
		return true;
	},

	flatten: function (src) {
		var dst = [];
		for (var i = 0; i < arguments.length; i++)
			jj.flattenReal (dst, arguments [i]);
		return dst;
	},

	flattenReal: function (dst, src) {
		if (jj.isArray (src)) {
			for (var i = 0; i < src.length; i++) {
				jj.flattenReal (dst, src [i]);
			}
		} else {
			dst.push (src);
		}
	},

	alert: function () {
		switch (arguments.length) {
		case 1:
			return alert (jj.pretty (arguments [0]));
		case 2:
			return alert (jj.callSummary (arguments [0], arguments [1]));
		default:
			throw 'Invalid number of args for jj.alery: ' + arguments.length;
		}
	},

	isObject: function (any) {
		return typeof any == 'object';
	},

	isBoolean: function (any) {
		return typeof any == 'boolean';
	},

	isFunction: function (any) {
		return typeof any == 'function';
	},

	prettyArgs: function (args) {
		var s = '(';
		for (var i = 0; i < args.length; i++) {
			if (i > 0) s += ', ';
			s += jj.pretty (args [i]);
		}
		return s + ')';
	},

	argsSlice: function (args, offset, length) {
		if (offset == undefined) offset = 0;
		if (length == undefined) length = args.length - offset;
		if (length < 0) length = 0;
		var ret = Array (length);
		for (var i = offset, j = 0; i < offset + length; i++, j++) {
			ret [j] = i < args.length? args [i] : undefined;
		}
		return ret;
	},

	isUndefined: function (any) {
		return any === undefined;
	},

	isNull: function (any) {
		return any === null;
	},

	createNamedElement: function( type, name ) {
		var element;
		try {
			element = document.createElement('<'+type+' name="'+name+'">');
		} catch (e) { }
		if (!element || !element.name) { 
			element = document.createElement(type);
			element.name = name;
		}
		return element;
	},

	inArray: function (search, array) {
		for (var i = 0; i < array.length; i++) {
			if (array [i] === search) return true;
		}
		return false;
	},

	randomChoice: function (array) {
		return array [Math.floor (array.length * Math.random ())];
	},

	anyInArray: function (searches, array) {
		for (var i = 0; i < searches.length; i++) {
			for (var j in array)
				if (array[j] == searches[i]) return true;
		}
		return false;
	},

	join: function () {
		var ret = [];
		return ret.concat.apply (ret, jj.argsSlice (arguments));
	},

	joinInto: function (arr) {
		for (var i = 1; i < arguments.length; i++) {
			for (var j = 0; j < arguments [i].length; j++) {
				arr.push (arguments [i] [j]);
			}
		}
		return arr;
	},

	coalesce: function () {
		for (var i = 0; i < arguments.length; i++) {
			if (arguments [i] != null && arguments [i] != undefined)
				return arguments [i];
		}
		return undefined;
	},

	arrayDel: function (array, elem) {
		var i = array.indexOf (elem);
		if (i >= 0) {
			array.splice (i, 1);
		}
	},

	firstToUpper: function (str) {
		if (str.length == 0) return '';
		return str.substr (0, 1).toUpperCase () + str.substr (1);
	},

	pluralize: function (num, singular, plural) {
		if (! plural) plural = singular + 's';
		if (num == 1) return '1 ' + singular;
		return String (num) + ' ' + plural;
	},

	toYmd: function (date) {
		return '' +
			jj.zeroPad (date.getFullYear (), 4) + '-' +
			jj.zeroPad (date.getMonth () + 1, 2) + '-' +
			jj.zeroPad (date.getDate (), 2);
	},

	zeroPad: function (num, digits) {
		var s = String (num);
		while (s.length < digits)
			s = '0' + s;
		return s;
	},

	numberFormat: function (num, before, after) {
		var prefix = jj.zeroPad (Math.floor (num), before);
		num = Math.abs (num);
		num = num - Math.floor (num);
		for (var i = 0; i < after; i++) num = num * 10;
		num = Math.round (num);
		var suffix = String (num)
		while (suffix.length < after) suffix = '0' + suffix;
		return prefix + '.' + suffix;
	},

	mapHas: function (map, name) {
		return Object.prototype.propertyIsEnumerable.apply (map, [ name ]);
	},

	mapCount: function (map) {
		var ret = 0;
		for (var key in map) ret++;
		return ret;
	},

	isArguments: function (any) {
		if (typeof any != 'object') return false;
		if (jj.mapCount (any) != 0) return false;
		if (! Object.prototype.hasOwnProperty.apply (any, [ 'length' ])) return false;
		return true;
	},

	mapEmpty: function (map) {
		for (var key in map) { return false; }
		return true;
	},

	
	arrayMerge: function () {
		var set = {}, ret = [];
		for (var i = 0; i < arguments.length; i++) {
			for (var j = 0; j < arguments [i].length; j++) {
				var val = arguments [i] [j];
				if (set [val]) continue;
				set [val] = true;
				ret.push (val);
			}
		}
		return ret;
	},
	
	arrayMergeInto: function (dst) {

		
		var set = {};
		for (var j = 0; j < dst.length; j++) {
			set [dst [j]] = true;
		}

		
		for (var i = 1; i < arguments.length; i++) {
			for (var j = 0; j < arguments [i].length; j++) {
				var val = arguments [i] [j];
				if (set [val]) continue;
				set [val] = true;
				dst.push (val);
			}
		}

		
		return dst;
	},
	
	arrayDiff: function (plus) {
		var set = {}, ret = [];
		for (var i = 1; i < arguments.length; i++) {
			for (var j = 0; j < arguments [i].length; j++) {
				set [arguments [i] [j]] = true;
			}
		}
		for (var i = 0; i < plus.length; i++) {
			if (! set [plus [i]])
				ret.push (plus [i]);
			set [plus [i]] = true;
		}
		return ret;
	},

	arrayUniq: function (arr) {
		var set = {}, ret = [];
		for (var i = 0; i < arr.length; i++) {
			if (set [arr [i]]) continue;
			set [arr [i]] = true;
			ret.push (arr [i]);
		}
		return ret;
	},

	formatCountry: function(country, region, city){
		var locationString = '';
		locationString = locationString + country;
		if(region){
			locationString = locationString + ', '+ region;
		}
		if(city){
			locationString = locationString + ', '+ city;
		}
		return locationString;
	},

	formatDate: function (dob) {
		splitDob = dob.split('-');
		var dob = new Date(splitDob[0], splitDob[1]-1, splitDob[2]);
		var today = new Date();
		var year = today.getFullYear();
		var roughAge = year - splitDob[0];
		today.setFullYear(splitDob[0]);
		if ((today-dob) < 0) roughAge -= 1;
		return roughAge;
	},

	ifUndef: function () {
		for (var i = 0; i < arguments.length; i++) {
			if (arguments [i] == undefined) continue;
			return arguments [i];
		}
		return undefined;
	},
	
	arrayMap: function (arr, fn) {
		var ret = new Array (arr.length);
		for (var i = 0; i < arr.length; i++) {
			ret [i] = fn (arr [i]);
		}
		return ret;
	},

	spliceArray: function (array, index, count, data) {
		var temp = array.slice (index + count);
		array.splice (index);
		array.concat (data, temp);
	}
};

 


var Jjax = jj.def ('Jjax', {

	integerRegex: /^(0|[123456789][0123456789]*)$/,

	

	Jjax: function () {
	},

	

	
	

	makeXmlHttpRequest: function () {
		if (window.XMLHttpRequest)
			return new XMLHttpRequest ();
		if (window.ActiveXObject)
			return new ActiveXObject ("Microsoft.XmlHttp");
		throw 'Unable to make XmlHttpRequest';
	},

	

	
	

	openXmlHttpRequest: function (req, a, b, c) {
		req.open (a, b, c);
	},

	

	
	
	
	
	
	
	
	

	simpleGet: function (url, handler, timeout) {
		var running = true;

		
		handler = jj.handlerFunc (handler, false);

		
		var request = this.makeXmlHttpRequest ();
	
		request.onreadystatechange = function () {

			
			if (! running) return;

			
			if (request.readyState != 4) return;

			
			var status = undefined;
			try { status = request.status; } catch (e) { }

			
			window.setTimeout (
				jj.bind (
					thisJjax,
					thisJjax.callHandler,
					handler,
					status == 200? 'onSuccess' : 'onFailure',
					[ request ]),
				0);

			
			running = false;
			delete request.onreadystatechange;
			delete request;
			delete handler;
		};

		
		this.openXmlHttpRequest (request, 'GET', url, true);
		request.send (null);

		
		if (timeout) setTimeout (function () {
			if (! running) return;

			
			request.abort ();

			
			handler ('onTimeout', [ request ]);

			
			running = false;
			delete request.onreadystatechange;
			delete request;
			delete handler;

		}, timeout);

		
		return {
			cancel: function () {
				if (! running) return;

				
				request.abort ();

				
				running = false;
				delete request.onreadystatechange;
				delete request;
				delete handler;
			}
		};

	},

	

	
	
	
	
	
	
	
	

	simplePost: function (url, contentType, body, handler, timeout) {
		var thisJjax = this;

		
		var running = true;

		
		handler = jj.handlerFunc (handler, false);

		
		var request = this.makeXmlHttpRequest ();

		request.onreadystatechange = function () {

			
			if (! running) return;

			
			if (request.readyState != 4) return;

			
			var status = undefined;
			try { status = request.status; } catch (e) { }

			
			window.setTimeout (
				jj.bind (
					thisJjax,
					thisJjax.callHandler,
					handler,
					status == 200? 'onSuccess' : 'onFailure',
					[ request ]),
				0);

			
			running = false;
			delete request.onreadystatechange;
			delete request;
			delete handler;
		};

		
		this.openXmlHttpRequest (request, 'POST', url, true);
		if (contentType)
			request.setRequestHeader ('Content-Type', contentType);
		request.send (body);

		
		if (timeout) setTimeout (function () {
			if (! running) return;
			
			
			request.abort ();

			
			thisJjax.callHandler (handler, 'onTimeout', [ request ]);
			
			
			running = false;
			delete request.onreadystatechange;
			delete request;
			delete handler;

		}, timeout);

		
		return {
			cancel: function () {

				
				if (! running) return;

				
				request.abort ();

				
				running = false;
				delete request.onreadystatechange;
				delete request;
				delete handler;
			}
		};
	},

	callHandler: function (handler, name, args) {
		var thisJjax = this;
		
			handler (name, args);
		
		
		
	},

	handlerException: function (name, args, exception) {
		if (flare.settings.version == 'trunk')	 alert ('Jjax caught exception in ' + name + ': ' + jj.errorSummary (exception));
	},

	toPhp: function (data) {
	
		if (data == undefined) {
			return 'N;';
		}
	
		if (typeof data == 'number') {
			if (! jj.isInt (data)) {
				return 'i:' + String (data) + ';';
			} else if (isNaN (data)) {
				return 'd:NAN;';
			} else {
				return 'd:' + String (data) + ';';
			}
		}
	
		if (typeof data == 'string') {
			return 's:' + jj.utfLen (data) + ':"' + data + '";';
		}
	
		if (typeof data == 'array' || data.constructor == Array) {
			var s = 'a:' + data.length + ':{';
			for (var i = 0; i < data.length; i++) {
				s += 'i:' + i + ';' + jjax.toPhp (data [i]);
			}
			return s + '}';
		}
	
		if (typeof data == 'object') {
			var keys = 0;
			for (var key in data) keys++;
			var s = 'a:' + keys + ':{';
			for (var key in data) {
				if ((typeof key == 'string' || key.constructor == String) && jjax.integerRegex.test (key))
					key = Number (key); 
				s += jjax.toPhp (key) + jjax.toPhp (data [key]);
			}
			return s + '}';
		}
	
		if (typeof data == 'boolean') {
			return 'b:' + (data? '1' : '0') + ';';
		}
	
		throw 'Don\'t know what to do with ' + typeof (data);
	},

	
	toJson: function (data) {
	
		if (data == undefined) {
			return 'undefined';
		}
	
		if (data == null) {
			return 'null';
		}

		if (typeof data == 'number') {
			return '' + data;
		}
	
		if (typeof data == 'string') {
			return '\'' + data
				.replace (/\u005c/g, '\\\\')
				.replace (/\u0027/g, '\\\'')
				.replace (/\u0000/g, '\\u0000')
				.replace (/\u0008/g, '\\b')
				.replace (/\u0009/g, '\\t')
				.replace (/\u000a/g, '\\n')
				.replace (/\u000b/g, '\\v')
				.replace (/\u000c/g, '\\f')
				.replace (/\u000d/g, '\\r')
				+ '\'';
		}
	
		if (typeof data == 'array' || data.constructor == Array) {
			var s = '[';
			var first = true;
			for (var i = 0; i < data.length; i++) {
				if (! first) s += ',';
				s += jjax.toJson (data [i]);
				first = false;
			}
			return s + ']';
		}

		if (typeof data == 'object') {
			var s = '{';
			var first = true;
			for (var key in data) {
				if (! first) s += ',';
				s += jjax.toJson (key) + ':' + jjax.toJson (data [key]);
				first = false;
			}
			return s + '}';
		}

		if (typeof data == 'boolean') {
			return data? 'true' : 'false';
		}
	
		throw 'Trying to encode ' + data;
	},

	fromJson: function (data) {
		try {
			return eval ('(' + data + ')');
		} catch (e) {
			throw 'Invalid JSON: ' + data;
		}
	}
});



var jjax = new Jjax ();

 


var beacon = {

	
	conv: {
	
		js: {
			contentType: 'text/javascript; charset=utf-8',
			encode: function (source) { return jjax.toJson (source); },
			decode: function (source) { return jjax.fromJson (source); }
		},
	
		php: {
			contentType: 'application/vnd.php.serialized; charset=utf-8',
			encode: function (source) { return jjax.toPhp (source); }
		}
	}
};

 



jj.mergeInto (beacon, {

	BeaconXhrClient: jj.def ('BeaconXhrClient', {

		BeaconXhrClient: function (url, convUp, convDown, timeout) {
			this.url = url;
			this.jjax = new Jjax ();
			this.convUp = convUp;
			this.convDown = convDown;
			this.timeout = timeout;
		},
	
		call: function (name, args, handlerAny) {
			return this.callFunc (name, args, jj.handlerFunc (handlerAny));
		},

		
		callFunc: function (name, args, handlerFunc) {
			var thisBeaconXhrClient = this;

			
			var req = {
				name: name,
				args: args };
			var reqStr = this.convUp.encode (req);

			
			var jjaxHandler = {

				onSuccess: function (xhr) {
					

						
						var resp;
						try {
							resp = thisBeaconXhrClient.convDown.decode (xhr.responseText);
						} catch (e) {
							
							handlerFunc ('failed', [ 'Unrecognised response from server: ' + xhr.responseText ]);
							return;
						}

						
						if ('debug' in resp)
							for (var i in resp.debug)
								alert ('Beacon debug: ' + resp.debug [i]);

						
						
							handlerFunc (resp.name, resp.args);
						
						
						
						
						

					
					
					
				},

				onFailure: function (xhr) {
					handlerFunc ('failed', [ 'HTTP request failed with status ' + xhr.status ]);
				},

				onTimeout: function (xhr) {
					handlerFunc ('timeout', [ 'HTTP request timed out' ]);
				}
			};

			
			this.jjax.simplePost (this.url, this.convUp.contentType, reqStr, jjaxHandler, this.timeout);
		},
		
		onHandlerError: function (e) {
		if (flare.settings.version == 'trunk')	 alert ('Beacon caught exception in response handler: ' + jj.errorSummary (e));
		}
	})
});

 


jj.mergeInto (beacon, {	

	makeXhrClient: function (url, conv) {
	
		
		if (! conv) conv = 'js';
		var temp = conv.split ('/');
		var from = conv, to = conv;
		if (temp.length == 2) {
			from = temp [0];
			to = temp [1];
		}
		
		if (! (from in beacon.conv) || ! ('encode' in beacon.conv [from]))
			throw 'Unsupported request format: ' + from;
		if (! (to in beacon.conv) || ! ('decode' in beacon.conv [to]))
			throw 'Unsupported response format: ' + to;

		
		return new beacon.BeaconXhrClient (url, beacon.conv [from], beacon.conv [to]);
	}
});

 


var md5 = {

	
	hash: function (x, len) {

		
		x [len >> 5] |= 0x80 << ((len) % 32);
		x [(((len + 64) >>> 9) << 4) + 14] = len;
	
		var a =  1732584193;
		var b = -271733879;
		var c = -1732584194;
		var d =  271733878;
	
		for (var i = 0; i < x.length; i += 16) {
			var olda = a;
			var oldb = b;
			var oldc = c;
			var oldd = d;
	
			a = md5.ff (a, b, c, d, x [i+ 0], 7 , -680876936);
			d = md5.ff (d, a, b, c, x [i+ 1], 12, -389564586);
			c = md5.ff (c, d, a, b, x [i+ 2], 17,  606105819);
			b = md5.ff (b, c, d, a, x [i+ 3], 22, -1044525330);
			a = md5.ff (a, b, c, d, x [i+ 4], 7 , -176418897);
			d = md5.ff (d, a, b, c, x [i+ 5], 12,  1200080426);
			c = md5.ff (c, d, a, b, x [i+ 6], 17, -1473231341);
			b = md5.ff (b, c, d, a, x [i+ 7], 22, -45705983);
			a = md5.ff (a, b, c, d, x [i+ 8], 7 ,  1770035416);
			d = md5.ff (d, a, b, c, x [i+ 9], 12, -1958414417);
			c = md5.ff (c, d, a, b, x [i+10], 17, -42063);
			b = md5.ff (b, c, d, a, x [i+11], 22, -1990404162);
			a = md5.ff (a, b, c, d, x [i+12], 7 ,  1804603682);
			d = md5.ff (d, a, b, c, x [i+13], 12, -40341101);
			c = md5.ff (c, d, a, b, x [i+14], 17, -1502002290);
			b = md5.ff (b, c, d, a, x [i+15], 22,  1236535329);
		
			a = md5.gg (a, b, c, d, x [i+ 1], 5 , -165796510);
			d = md5.gg (d, a, b, c, x [i+ 6], 9 , -1069501632);
			c = md5.gg (c, d, a, b, x [i+11], 14,  643717713);
			b = md5.gg (b, c, d, a, x [i+ 0], 20, -373897302);
			a = md5.gg (a, b, c, d, x [i+ 5], 5 , -701558691);
			d = md5.gg (d, a, b, c, x [i+10], 9 ,  38016083);
			c = md5.gg (c, d, a, b, x [i+15], 14, -660478335);
			b = md5.gg (b, c, d, a, x [i+ 4], 20, -405537848);
			a = md5.gg (a, b, c, d, x [i+ 9], 5 ,  568446438);
			d = md5.gg (d, a, b, c, x [i+14], 9 , -1019803690);
			c = md5.gg (c, d, a, b, x [i+ 3], 14, -187363961);
			b = md5.gg (b, c, d, a, x [i+ 8], 20,  1163531501);
			a = md5.gg (a, b, c, d, x [i+13], 5 , -1444681467);
			d = md5.gg (d, a, b, c, x [i+ 2], 9 , -51403784);
			c = md5.gg (c, d, a, b, x [i+ 7], 14,  1735328473);
			b = md5.gg (b, c, d, a, x [i+12], 20, -1926607734);
		
			a = md5.hh (a, b, c, d, x [i+ 5], 4 , -378558);
			d = md5.hh (d, a, b, c, x [i+ 8], 11, -2022574463);
			c = md5.hh (c, d, a, b, x [i+11], 16,  1839030562);
			b = md5.hh (b, c, d, a, x [i+14], 23, -35309556);
			a = md5.hh (a, b, c, d, x [i+ 1], 4 , -1530992060);
			d = md5.hh (d, a, b, c, x [i+ 4], 11,  1272893353);
			c = md5.hh (c, d, a, b, x [i+ 7], 16, -155497632);
			b = md5.hh (b, c, d, a, x [i+10], 23, -1094730640);
			a = md5.hh (a, b, c, d, x [i+13], 4 ,  681279174);
			d = md5.hh (d, a, b, c, x [i+ 0], 11, -358537222);
			c = md5.hh (c, d, a, b, x [i+ 3], 16, -722521979);
			b = md5.hh (b, c, d, a, x [i+ 6], 23,  76029189);
			a = md5.hh (a, b, c, d, x [i+ 9], 4 , -640364487);
			d = md5.hh (d, a, b, c, x [i+12], 11, -421815835);
			c = md5.hh (c, d, a, b, x [i+15], 16,  530742520);
			b = md5.hh (b, c, d, a, x [i+ 2], 23, -995338651);
		
			a = md5.ii (a, b, c, d, x [i+ 0], 6 , -198630844);
			d = md5.ii (d, a, b, c, x [i+ 7], 10,  1126891415);
			c = md5.ii (c, d, a, b, x [i+14], 15, -1416354905);
			b = md5.ii (b, c, d, a, x [i+ 5], 21, -57434055);
			a = md5.ii (a, b, c, d, x [i+12], 6 ,  1700485571);
			d = md5.ii (d, a, b, c, x [i+ 3], 10, -1894986606);
			c = md5.ii (c, d, a, b, x [i+10], 15, -1051523);
			b = md5.ii (b, c, d, a, x [i+ 1], 21, -2054922799);
			a = md5.ii (a, b, c, d, x [i+ 8], 6 ,  1873313359);
			d = md5.ii (d, a, b, c, x [i+15], 10, -30611744);
			c = md5.ii (c, d, a, b, x [i+ 6], 15, -1560198380);
			b = md5.ii (b, c, d, a, x [i+13], 21,  1309151649);
			a = md5.ii (a, b, c, d, x [i+ 4], 6 , -145523070);
			d = md5.ii (d, a, b, c, x [i+11], 10, -1120210379);
			c = md5.ii (c, d, a, b, x [i+ 2], 15,  718787259);
			b = md5.ii (b, c, d, a, x [i+ 9], 21, -343485551);
		
			a = md5.safeAdd (a, olda);
			b = md5.safeAdd (b, oldb);
			c = md5.safeAdd (c, oldc);
			d = md5.safeAdd (d, oldd);
		}
		return Array (a, b, c, d);
	},
	
	
	cmn: function (q, a, b, x, s, t) {
		return md5.safeAdd (md5.bitRol (md5.safeAdd (md5.safeAdd (a, q), md5.safeAdd (x, t)), s), b);
	},

	ff: function (a, b, c, d, x, s, t) {
		return md5.cmn ((b & c) | ((~b) & d), a, b, x, s, t);
	},

	gg: function (a, b, c, d, x, s, t) {
		return md5.cmn((b & d) | (c & (~d)), a, b, x, s, t);
	},
	
	hh: function (a, b, c, d, x, s, t) {
		return md5.cmn (b ^ c ^ d, a, b, x, s, t);
	},

	ii: function (a, b, c, d, x, s, t) {
		return md5.cmn (c ^ (b | (~d)), a, b, x, s, t);
	},

	
	hmac: function (bkey, data) {
		if (bkey.length > 16) bkey = core_md5 (bkey, key.length * 8);
	
		var ipad = Array (16), opad = Array (16);
		for (var i = 0; i < 16; i++) {
			ipad [i] = bkey [i] ^ 0x36363636;
			opad [i] = bkey [i] ^ 0x5C5C5C5C;
		}
	
		var hash = md5.hash (ipad.concat (data), 512 + data.length * 8);
		return md5.hash (opad.concat (hash), 512 + 128);
	},
	
	
	safeAdd: function (x, y) {
		var lsw = (x & 0xFFFF) + (y & 0xFFFF);
		var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
		return (msw << 16) | (lsw & 0xFFFF);
	},
	
	
	bitRol: function (num, cnt) {
		return (num << cnt) | (num >>> (32 - cnt));
	},

	
	str2binl: function (str, chrsz) {
		var bin = Array ();
		var mask = (1 << chrsz) - 1;
		for (var i = 0; i < str.length * chrsz; i += chrsz)
			bin [i>>5] |= (str.charCodeAt (i / chrsz) & mask) << (i%32);
		return bin;
	},
	
	
	binl2str: function (bin, chrsz) {
		var str = "";
		var mask = (1 << chrsz) - 1;
		for (var i = 0; i < bin.length * 32; i += chrsz)
			str += String.fromCharCode ((bin [i>>5] >>> (i % 32)) & mask);
		return str;
	},
	
	
	binl2hex: function (binarray) {
		var hexTab = "0123456789abcdef";
		var str = "";
		for (var i = 0; i < binarray.length * 4; i++) {
			str += hexTab.charAt ((binarray [i>>2] >> ((i%4)*8+4)) & 0xF)
				+ hexTab.charAt ((binarray [i>>2] >> ((i%4)*8  )) & 0xF);
		}
		return str;
	},
	
	
	binl2b64: function (binarray) {
		var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
		var str = "";
		for (var i = 0; i < binarray.length * 4; i += 3) {
			var triplet = (((binarray [i >> 2] >> 8 * (i % 4)) & 0xFF) << 16)
				| (((binarray [i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 0xFF) << 8)
				| ((binarray [i + 2 >> 2] >> 8 * ((i + 2) % 4)) & 0xFF);
			for (var j = 0; j < 4; j++) {
				if (i * 8 + j * 6 > binarray.length * 32) str += '=';
				else str += tab.charAt ((triplet >> 6 * (3 - j)) & 0x3F);
			}
		}
		return str;
	}
};


 


var utf8 = {

	
	encode: function (str) {
		var s = "";

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

			var c = str.charCodeAt (i);

			if (c < 128) {
				s += String.fromCharCode (c);
			}
			else if ((c > 127) && (c < 2048)) {
				s += String.fromCharCode ((c >> 6) | 192);
				s += String.fromCharCode ((c & 63) | 128);
			} else {
				s += String.fromCharCode ((c >> 12) | 224);
				s += String.fromCharCode (((c >> 6) & 63) | 128);
				s += String.fromCharCode ((c & 63) | 128);
			}
		}

		return s;
	},

	
	decode: function (utftext) {
		var s = "";
		var i = 0;
		var c, c1, c2;

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

			c = utftext.charCodeAt(i);

			if (c < 128) {
				s += String.fromCharCode(c);
			} else if ((c > 191) && (c < 224)) {
				c2 = utftext.charCodeAt (i+1);
				s += String.fromCharCode (((c & 31) << 6) | (c2 & 63));
				i++;
			} else {
				c2 = utftext.charCodeAt (i+1);
				c3 = utftext.charCodeAt (i+2);
				s += String.fromCharCode (((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 2;
			}
		}

		return s;
	}
};

 

	var Fader = function () {
		this.wantedOpacity = 100;
		this.opacity = 100;
		this.currentSpeed = 10;
		this.timerRunning = false;
		this.onComplete = false;
		 
	};

	Fader.prototype.init = function (elementObj) {
		
		this.element = elementObj;
		
	}
		
	Fader.prototype.fadeTo = function (opacity, speed, onComplete) {
		
		
		if (!this.element) return false;
		
		
		this.wantedOpacity = opacity;
		this.currentSpeed = speed;
		this.onComplete = onComplete;
		
		if (this.opacity != this.wantedOpacity) {

			if (this.timerRunning) {
				return true;
			} else {
				this.timerRunning = true;
				this.timerAjustOpacity();
			
			}
		} else if (this.opacity == this.wantedOpacity) {
			this.timerRunning = false;
			this.doOnComplete();
			return true;
		}
		return undefined;		
	}
	
	Fader.prototype.timerAjustOpacity = function () {
	
		
		
		if (!this.timerRunning) return;

		var newOpacity = 0;

		if (this.opacity < this.wantedOpacity) {
			newOpacity = this.opacity + this.currentSpeed;
			if (newOpacity > this.wantedOpacity) newOpacity = this.wantedOpacity;
		} else if (this.opacity > this.wantedOpacity) {
			newOpacity = this.opacity - this.currentSpeed;
			if (newOpacity < this.wantedOpacity) newOpacity = this.wantedOpacity;
		}
		
		
		this.setOpacity(newOpacity);
		
		
		if (newOpacity == this.wantedOpacity) {
			this.timerRunning = false;
			this.doOnComplete();
		} else {
			var thisObj = this;
			var fn = function () { thisObj.timerAjustOpacity (); };
			setTimeout (fn, 30);
			
		}
	}
	
	Fader.prototype.doOnComplete = function () {
		if (this.onComplete)
			this.onComplete ();
	}
	
	Fader.prototype.setOpacity = function (opacity) {

		this.opacity = opacity;

		opacity = (opacity == 100)?99.999:opacity;
	
		
		this.element.style.filter = "alpha(opacity:"+opacity+")";
		
		
		this.element.style.KHTMLOpacity = opacity/100;
		
		
		this.element.style.MozOpacity = opacity/100;
		
		
		this.element.style.opacity = opacity/100;
	}
	

 


	var Merger = function (width, height) {
	
		this.width = width;
		this.height = height;
		this.visable = 1;
		this.fader_1;
		this.fader_2;
		this.fade_speed = 4;
		this.domobj_1;
		this.domobj_2;
		this.container;
		this.init();
	}
	
	Merger.prototype.init = function () {
		this.container = document.createElement('div');
		this.domobj_1 = document.createElement('div');
		this.domobj_2 = document.createElement('div');
		this.container.style.height = this.height;
		this.container.style.width = this.width;
		this.container.style.overflow = "hidden";
		this.domobj_1.style.height = this.height;
		this.domobj_1.style.width = this.width;
		this.domobj_1.style.position = "relative";
		this.domobj_2.style.height = this.height;
		this.domobj_2.style.width = this.width;
		this.domobj_2.style.top = "-"+this.height;
		this.domobj_2.style.position = "relative";
		this.container.appendChild(this.domobj_1);
		this.container.appendChild(this.domobj_2);
		this.initFader();
	}
	
	Merger.prototype.initFader = function () {
		this.fader_1 = new Fader();
		this.fader_2 = new Fader();
		this.fader_1.init(this.domobj_1);
		this.fader_2.init(this.domobj_2);
		this.fader_1.setOpacity(100);
		this.fader_2.setOpacity(0);
	}
	
	Merger.prototype.returnHtml = function () {
		return this.container;
	}
	
	Merger.prototype.adjustWidth = function (width) {
		this.container.style.width = width;
		this.domobj_1.style.width = width;
		this.domobj_2.style.width = width;
	}

	Merger.prototype.setDomObj1 = function (dom) {
		while (this.domobj_1.firstChild)
			this.domobj_1.removeChild(this.domobj_1.firstChild);
		this.domobj_1.appendChild(dom);
	}
	
	Merger.prototype.setDomObj2 = function (dom) {
		while (this.domobj_2.firstChild)
			this.domobj_2.removeChild(this.domobj_2.firstChild);
		this.domobj_2.appendChild(dom);
	}
	
	Merger.prototype.setDomObjs = function (dom_1, dom_2) {
		this.setDomObj1(dom_1);
		this.setDomObj2(dom_2);
	}
	
	Merger.prototype.performSwap = function () {
		var thisobj = this;
		if(this.visable != 1){
			this.fader_2.fadeTo(0,this.fade_speed, function () {thisobj.domobj_2.style.display = 'none';});
			this.fader_1.fadeTo(100,this.fade_speed, function () {;});
			this.visable = 1;
		}else{
			this.fader_1.fadeTo(0,this.fade_speed, function () {;});
			this.domobj_2.style.display = 'block';
			this.fader_2.fadeTo(100,this.fade_speed, function () {;});
			this.visable = 2;
		}
	}
 

	var Slider = function () {
		this.currentSpeed = 10;
		this.timerRunning = false;
		this.onComplete = false;
	}
	
	Slider.prototype.init = function (elementObj) {
		this.element = elementObj;
		
		this.wantedX = this.stripPx(this.element.style.left);
		this.currentX =  this.wantedX;
	}
	
	Slider.prototype.stripPx = function (inValue) {
		return inValue.substr(0,inValue.length-2);
	}	
	
	Slider.prototype.slideTo = function (wantedX, speed, onComplete) {
		
		
		if (!this.element) return false;
		
		
		this.wantedX = wantedX;
		this.currentSpeed = speed;
		this.onComplete = onComplete;
		
		if (this.currentX != this.wantedX) {

			if (this.timerRunning) {
				return true;
			} else {
				this.timerRunning = true;
				this.timerAjustPosition();
			
			}
		} else if (this.currentX == this.wantedX) {
			this.timerRunning = false;
			this.doOnComplete();
			return true;
		}
		return undefined;		
	}
	
	Slider.prototype.timerAjustPosition = function () {
	
		
		
		if (!this.timerRunning) return;

		var newX = 0;

		if (this.currentX < this.wantedX) {
			newX = this.currentX + this.currentSpeed;
			if (newX > this.wantedX) newX = this.wantedX;
		} else if (this.currentX > this.wantedX) {
			newX = this.currentX - this.currentSpeed;
			if (newX < this.wantedX) newX = this.wantedX;
		}
		
		
		this.setPosition(newX, 0);
		
		
		if (newX == this.wantedX) {
			this.timerRunning = false;
			this.doOnComplete();
		} else {
			var thisObj = this;
			var fn = function () { thisObj.timerAjustPosition (); };
			setTimeout (fn, 40);	
		}
	}
	
	Slider.prototype.doOnComplete = function () {
		if (this.onComplete)
			this.onComplete ();
	}
	
	Slider.prototype.setPosition = function (newX, newY) {

		this.currentX = newX;
		this.element.style.left = String(newX)+'px';

		
	}
	

 
var FormGuiObject = function (formObj) {
	
	this.formObj = formObj;	
	this.bubble = document.getElementById('bubbleTip');
	this.bubbleFocus = 0;
	this.bubble = document.getElementById('bubbleTip');
	this.elementWithFocus = -1;
	this.topOffset = 0;
}


FormGuiObject.prototype.init = function () {


	var thisObj = this;





	
}

FormGuiObject.prototype.setOpacity  = function (domObj, opacity) {

	opacity = (opacity == 100)?99.999:opacity;

	domObj.style.filter = "alpha(opacity:"+opacity+")"; 
	domObj.style.KHTMLOpacity = opacity / 100;   		
	domObj.style.MozOpacity = opacity / 100;   			
	domObj.style.opacity = opacity / 100;  				
	
}

FormGuiObject.prototype.bubbleFade = function (desiredOpacity,currentTop) {
return;
	var bubble = document.getElementById('bubbleTip');
	if (bubble.style.top != currentTop) return;
	
	if (desiredOpacity < (bubble.style.opacity*100)) {
		
		var newOpacity = (bubble.style.opacity*100) - 20;
		if (newOpacity < desiredOpacity) newOpacity = desiredOpacity;
		this.setOpacity (bubble, newOpacity);
		if (newOpacity == 0) bubble.style.top = -1000;
	} else {
		
		var newOpacity = (bubble.style.opacity*100) + 10;
		if (newOpacity > desiredOpacity) newOpacity = desiredOpacity;
		this.setOpacity (bubble, newOpacity);
	}
	
	if ((bubble.style.opacity*100) != desiredOpacity) 
	window.setTimeout("FormObject['register'].GuiObject.bubbleFade('"+desiredOpacity+"','"+currentTop+"')",100);

	
}

 



var FormObject = function (formName) {

	this.formName = formName;
	this.elementArr = [];
	this.elementMap = {};
	this.gui	= new FormGuiObject(this);
	this.bubbleFocus = 0;
	this.bubble = null;
	this.bubbleText = null;
	this.elementWithFocus = -1;
	this.fader = new Fader();
	
	this.caption = {
		'default'		: 	'Submit',
		'modified'		: 	'Save Changes',
		'saving'		: 	'Saving Now...',
		'saved'			: 	'Saved',
		'errorSaving'	:	'Error Saving',
		'notValid'		:	'Please Revise'
	}
}

FormObject.prototype.addElement = function (elementObject) {

	this.elementArr.push (elementObject);
	this.elementArr[(this.elementArr.length-1)].init(this);
	this.elementMap[elementObject.settings.ref] = elementObject;

}

FormObject.prototype.updateFields = function (formRef,data) {
	for (i in data[formRef]) {
		try {
		if (this.elementMap[i]) this.elementMap[i].updateValue (data[formRef][i])
		} catch (e) { }
	}	
}

FormObject.prototype.postRender = function () {


	return;
	

	
}
FormObject.prototype.updateSubmitCaption = function (state) {

	var formSubmit = document.getElementById('submit_'+this.formName);
	formSubmit.value = this.caption[state];
	
	
}

FormObject.prototype.setValidates = function (state) {
	
	var formSubmit = document.getElementById('submit_'+this.formName);
	
	switch(state) {
		case true:

	
			
		break;
		case false:
	
	
		
		break;		
	}
	
}


FormObject.prototype.validateAll = function () {
	
	for (e in this.elementArr) {
		if (!this.elementArr[e].goValidate()) {
			this.updateSubmitCaption('notValid');
			return false;
		}	
	}
	
	return true;
}
FormObject.prototype.elementChanged = function () {
	this.updateSubmitCaption('modified');
}
FormObject.prototype.createBubble = function () {


	var bubble 				= document.createElement('span');
	bubble.id 				= this.formName+'_bubbleTip';
	bubble.style.position 	= 'absolute';
	bubble.style.display 	= 'block';
	bubble.style.zIndex 	= '10';
	bubble.style.top		= '10px';
	bubble.style.left		= '25px';
	bubble.style.visibility 		= 'hidden';

	var tooltip = document.createElement('span');
	tooltip.style.display 	= 'block';
	tooltip.className 		= 'tooltip';

	var bubbleTop = document.createElement('span');
	bubbleTop.className 		= 'top';
	bubbleTop.style.display 	= 'block';

	var bubbleMain 						= document.createElement('div');
	bubbleMain.style.width 				= '180px';
	
		var bubbleHeader 					= document.createElement('div');
		bubbleHeader.style.marginBottom 	= '4px';
		bubbleHeader.style.fontWeight 		= 'bold';
		bubbleHeader.appendChild(			document.createTextNode('problem with element'));
		

		var bubbleExplanation = document.createElement('span');
		bubbleExplanation.appendChild(document.createTextNode('explanation'));
		bubbleMain.appendChild(bubbleExplanation);

	var bubbleBottom = document.createElement('b');
	bubbleBottom.style.display 	= 'block';	
	bubbleBottom.className 	= 'bottom';	


	bubbleTop.appendChild(bubbleMain);
	tooltip.appendChild(bubbleTop);
	tooltip.appendChild(bubbleBottom);
	
	bubble.appendChild(tooltip);
	this.gui.setOpacity(bubble, 90);
	this.bubble = bubble;
	this.bubbleText = bubbleExplanation;
	
	this.fader.init(bubble);
	this.fader.setOpacity(0);
	
	return bubble;
}

FormObject.prototype.returnHtml = function () {
	var thisForm = this;


	var outDom = document.createElement('div');
	outDom.style.position = 'relative';
	
	outDom.appendChild(this.createBubble());
	
	var formTable = document.createElement('table');
	formTable.id = 'form';
	formTable.name = 'table_'+this.formName;
	
	var tableBody = document.createElement( 'tbody' );
	tableBody.id = 'formbody';
	tableBody.name = 'tbody_'+this.formName;
	
	formTable.appendChild(tableBody);


	for (e in this.elementArr) {
		
		
		if (this.elementArr[e].overRideRow) {
			
		} else {
			
			var cRow = document.createElement('tr');
			
			
			if (this.elementArr[e].returnCaption()) {
			var cCell1 = document.createElement('td');
				cCell1.className = 'caption';
				cCell1.id = 'caption_'+this.elementArr[e].settings.ref;
				cCell1.appendChild(this.elementArr[e].returnCaption());
			}
			var cCell2 = document.createElement('td');
				cCell2.appendChild(this.elementArr[e].returnInput());
				if (this.inputColWidth && this.elementArr[e].returnCaption()) {
					cCell2.style.width = String(this.inputColWidth)+'px';
					
				}
				
			
			if (!this.elementArr[e].returnCaption()) {
				cCell2.colSpan = '2';
			}
			var cCell3 = document.createElement('td');
				cCell3.className = 'statusIcon';
				cCell3.appendChild(this.elementArr[e].returnInput());

				var statusIcon = document.createElement('img');
				statusIcon.src = 'data/img/blank.gif';
				statusIcon.id = 'status_'+this.elementArr[e].settings.ref;
				statusIcon.style.width = '16px';
				cCell3.appendChild(statusIcon);
				
			
			
			if (this.elementArr[e].returnCaption()) cRow.appendChild(cCell1);
			cRow.appendChild(cCell2);
			
			tableBody.appendChild(cRow);

			
				delete cRow;		delete cCell1;
				delete cCell2;		delete cCell3;
				delete statusIcon;

		}
	}

	var buttonRow = document.createElement('tr');
	var buttonRowCell = document.createElement('td');   
	
	buttonRowCell.setAttribute ('colSpan', '3');
	buttonRowCell.className = 'formButtons';
	var buttonSubmit = document.createElement('input');
	buttonSubmit.type = 'submit';
	buttonSubmit.value = this.caption['default'];
	buttonSubmit.className = 'inputSubmit';
	buttonSubmit.id = 'submit_'+this.formName;
	var formObj = this;
	buttonSubmit.onclick = function () {	
		if (formObj.validateAll()) {
			this.value = formObj.caption['saving'];
			var returnArr = {};
			for (i in formObj.elementArr) {
				var elemData = formObj.elementArr[i].returnValueArr();
				returnArr [elemData [0]] = elemData [1];
				delete elemData;
			}
			
			if (thisForm.onSubmit (returnArr)) this.value = formObj.caption['saved'];
			else this.value = formObj.caption['errorSaving'];
		}
		
	}
	
	buttonRowCell.appendChild(buttonSubmit);
	buttonRow.appendChild(buttonRowCell);
	tableBody.appendChild(buttonRow);

	outDom.appendChild(formTable);
	return outDom;
}
 

var AbstractElement = jj.def ('AbstractElement', {

	AbstractElement: function (settings) {
		this.settings = settings;
		this.className = 'inputText';
		this.formObj = null;
	},

	init: function (formObj) {
		this.formObj = formObj;
	},

	returnCaption: function () {
		if (!this.settings.caption) return false;
		
		return document.createTextNode(this.settings.caption);
	},

	returnInput: function () {
		
		var inputButton = jj.createNamedElement('input', this.settings.ref);
		inputButton.id = this.formObj.formName+'_'+this.settings.ref;
		if (this.settings.value) inputButton.value = this.settings.value;
		inputButton.onchange = jj.bind(this.formObj,'elementChanged');

		thisObj = this;
		inputButton.onfocus = function () { thisObj.changeStatus('focus'); thisObj.elemOnFocus(); }
		inputButton.onblur = function () { thisObj.changeStatus('blur'); thisObj.elemOnBlur(); }
		
		return inputButton;

	},
	updateValue: function (value) {
		
		this.settings.value = value;
		document.getElementById(this.formObj.formName+'_'+this.settings.ref).value = this.settings.value;
				
	},

	postRender: function () {
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		var thisObj = this;
		
	
	},
	
	elemOnFocus: function () {
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},
	
	elemOnBlur: function () {
		this.goValidate ();
	},
	returnValueArr: function () {
		
		return [this.settings.ref,document.getElementById(this.formObj.formName+'_'+this.settings.ref).value];
		
		
	},
	goValidate: function () {
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		var caption = document.getElementById ('caption_'+this.settings.ref);
		
		thisForm = this.formObj;
			var makeInvisible = function () {
			thisForm.bubble.style.visibility 		= 'hidden';
			thisForm.gui.bubbleFocus = null;
		}

	
		if (this.validate()) {
			this.formObj.setValidates(true);
			if (this.formObj.gui.bubbleFocus == this.settings.ref) {
				

				this.formObj.fader.fadeTo(0,10, makeInvisible);	
				
			}
			if (element.value) this.changeStatus('valid');
			caption.className = 'caption';
			return true;
		} else {
			this.formObj.setValidates(false);
			this.changeStatus('notValid');
			element.className = this.className+'_notValid';
			caption.className = 'caption_notValid';
			
			if (this.formObj.gui.bubbleFocus != this.settings.ref) {
				
				this.formObj.gui.bubbleFocus = this.settings.ref;
				this.formObj.bubble.style.top = String(this.formObj.gui.topOffset+ caption.offsetTop+13)+ 'px';
				
				this.formObj.bubble.style.visibility 		= 'visible';
				this.formObj.bubble.style.zIndex = '99';
				this.formObj.fader.fadeTo(90,10, false);	
				var cRef = this.settings.ref;
				var fObj = this.formObj;
				var fn = function () {
					if (fObj.gui.bubbleFocus == cRef) 
					fObj.fader.fadeTo(0,10, makeInvisible);	
				}
				window.setTimeout(fn,6000);
				
			
			
			}
		return false;
		}
		
	},
	
	validate: function () {
		if (!this.settings.validators) return true;
		
		var errorMsgs = document.createDocumentFragment();
		var errors = 0;
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		for (v in this.settings.validators) {
			if (!this.settings.validators[v].validate(element.value)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[v].errMsg+' '));
				errors = errors + 1;
			}
		}
		if (errors < 1)	return true;
		else {
			
			this.formObject
			while (this.formObj.bubbleText.firstChild)  this.formObj.bubbleText.removeChild(this.formObj.bubbleText.firstChild);
			
			this.formObj.bubbleText.appendChild(errorMsgs);
			
			
		
			return false;
		}
	},
	
	changeStatus: function (newStatus) {
	
		return;
		var statusIcon = document.getElementById('status_'+this.settings.ref);

 	if (this.userAgent == undefined) {
 		this.userAgent = new UserAgent(this);
 		this.userAgent.init();
 	}	
		
		switch (newStatus) {
			case 'focus':
			statusIcon.src = flare.cUrl+this.userAgent.silkUrl( 'keyboard' ); 
			break;
			case 'blur':
			statusIcon.src = flare.cUrl+this.userAgent.silkUrl( 'blank' ); 
			break;
			case 'valid':
			statusIcon.src = flare.cUrl+this.userAgent.silkUrl( 'tick' ); 
			break;
			case 'notValid':
			statusIcon.src = flare.cUrl+this.userAgent.silkUrl( 'cross' );
			break;
		}
	}
});

 
var AgeRangeElement = jj.def ('AgeRangeElement', AbstractElement, {
	AgeRangeElement: function (settings) {
		this.options = settings.options;
		this.AbstractElement (settings);
		this.className = 'inputSelect';
	},
	
	popMinAge: function (minAgeObject) {
		for (var age = 18; age < 70; age++) {
			minAgeObject.appendChild( this.createOption( String(age )));
		}
		minAgeObject.appendChild( this.createOption( '70+' ));
	},
	
	popMaxAge: function (maxAgeObject) {
		for (var age = 18; age < 70; age++) {
			maxAgeObject.appendChild( this.createOption( String(age) ));
		}
		maxAgeObject.appendChild( this.createOption( '70+' ));		
	},
	
	createOption: function(value) {
	
		var option = jj.createNamedElement( 'option', value.replace(" ", ""));
		option.value = value;
		option.appendChild(document.createTextNode(value));
		return option;
	},

	returnInput: function () {
		var docFrag = document.createDocumentFragment();
		var thisobj = this;

		var inputButtonMinAge = jj.createNamedElement( 'select', this.settings.ref );
		inputButtonMinAge.id = this.formObj.formName+'_'+this.settings.ref+'_InputButtonMinAge';
		inputButtonMinAge.className = this.className;
		inputButtonMinAge.style.width = "50px";
		thisobj.popMinAge(inputButtonMinAge);
			
		var seperator = document.createElement( 'div' );
		seperator.style.paddingLeft = '8px';
		seperator.style.paddingRight = '5px';
		seperator.style.display = 'inline';
		seperator.appendChild( document.createTextNode( 'to') );
		
		var inputButtonMaxAge = jj.createNamedElement( 'select', this.settings.ref );
		inputButtonMaxAge.id = this.formObj.formName+'_'+this.settings.ref+'_InputButtonMaxAge';
		inputButtonMaxAge.className = this.className;
		inputButtonMaxAge.style.width = "50px";
		thisobj.popMaxAge(inputButtonMaxAge);
		
		inputButtonMaxAge.selectedIndex = 52;
		
		docFrag.appendChild(inputButtonMinAge);
		docFrag.appendChild(seperator);
		docFrag.appendChild(inputButtonMaxAge);
		return docFrag;			
	},
	
	returnValueArr: function () {
		var minAgeDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonMinAge');
		var minAgeValue = minAgeDom.options[minAgeDom.selectedIndex].value;
		if (!minAgeValue) minAgeValue = '18';
		
		var maxAgeDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonMaxAge');
		var maxAgeValue = maxAgeDom.options[maxAgeDom.selectedIndex].value;
		if (!maxAgeValue) maxAgeValue = '70+';
		
		return [this.settings.ref, {
			minAgeValue: minAgeValue, 
			maxAgeValue: maxAgeValue
		}]; 
	},

	validate: function () {
		if (!this.settings.validators) return true;
				
		return true;
	},
	
	goValidate: function () {
		return true;
	},
	
	updateValue: function (value) {		
	}
			
});
 


var DateElement = jj.def ('DateElement', AbstractElement, {

	DateElement: function (settings) {
		this.options = settings.options;
		this.AbstractElement (settings);
		this.className = 'inputSelect';
	},
	popDays: function(daySelectObject){
		
		var day_array = new Array("01", "02","03","04", "05","06","07", "08", "09", "10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31");
		daySelectObject.appendChild(this.createOption('dd'));
		for (i in day_array){
				daySelectObject.appendChild(this.createOption(day_array[i]));
		}
	},
	popMonths: function(monthSelectObject){
		
		var mon_array = new Array("January", "February","March","April", "May","June","July", "August", "September", "October","November","December");
		for (i in mon_array){
				monthSelectObject.appendChild(this.createOption(mon_array[i]));
		}
	},
	popYears: function(yearSelectObject){
		var curdate = new Date();
		year = curdate.getFullYear();
		var option = jj.createNamedElement( 'option', 'initial');
		option.value = 'yyyy';
		option.appendChild(document.createTextNode('yyyy'));
		yearSelectObject.appendChild(option);
		delete option;
		while (year != 1920){
			var option = document.createElement('option');
			option.name = year;
			option.value = year;
			option.appendChild(document.createTextNode(year));
			yearSelectObject.appendChild(option);
			delete option;
			year--;
		}
	},
	createOption: function(value) {
	
		var option = jj.createNamedElement( 'option', value.replace(" ","") );
		option.value = value;
		option.appendChild(document.createTextNode(value));
		return option;
	},
	returnInput: function () {
		var docFrag = document.createDocumentFragment();
		var thisobj = this;
		
		var inputButtonDay = jj.createNamedElement( 'select', this.settings.ref );
		inputButtonDay.id = this.formObj.formName+'_'+this.settings.ref+'_InputButtonDay';
		inputButtonDay.className = this.className;
		inputButtonDay.style.width = "45px";
		thisobj.popDays(inputButtonDay);
		
		var inputButtonMonth = document.createElement('select');
		inputButtonMonth.id = this.formObj.formName+'_'+this.settings.ref+'_InputButtonMonth';
		inputButtonMonth.className = this.className;
		inputButtonMonth.style.width = "90px";
		thisobj.popMonths(inputButtonMonth);
		
		var inputButtonYear = document.createElement('select');
		inputButtonYear.id = this.formObj.formName+'_'+this.settings.ref+'_InputButtonYear';
		inputButtonYear.className = this.className;
		inputButtonYear.style.width = "75px";
		thisobj.popYears(inputButtonYear);
		
		
		docFrag.appendChild(inputButtonDay);
		docFrag.appendChild(inputButtonMonth);
		docFrag.appendChild(inputButtonYear);
		return docFrag;	
	},

	elemOnFocus: function () {
		
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},
	returnValueArr: function () {
		
		
		
		
		var dayDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonDay');
		var dayValue = dayDom.options[dayDom.selectedIndex].value;
		if (!dayValue) dayValue = null;
		var monthDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonMonth');
		var monthValue;
		if (monthDom.selectedIndex > -1){
			var monthValue = monthDom.options[monthDom.selectedIndex].value;
		}
		if (!monthValue) monthValue = null;
		var yearDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonYear');
		var yearValue;
		if (yearDom.selectedIndex > -1){
			var yearValue = yearDom.options[yearDom.selectedIndex].value;
		}
		
		if (!yearValue) stateValue = null;
		
		monthNumber = monthDom.selectedIndex + 1;
		if (monthNumber < 10) monthNumber = '0' + monthNumber;
		
		return_value = yearValue+'-'+monthNumber+'-'+dayValue;
		
		return [this.settings.ref,return_value];
		
	},
	validate: function () {
		if (!this.settings.validators) return true;
		
		var errorMsgs = document.createDocumentFragment();
		var errors = 0;
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonDay');
		var element2 = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonMonth');
		var element3 = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonYear');
		var dayValue = element.options[element.selectedIndex].value;
		var monthValue = element2.selectedIndex + 1;
		if (monthValue < 10) monthValue = '0' + monthValue;
		var yearValue = element3.options[element3.selectedIndex].value;
		var dateString = monthValue+'/'+dayValue+'/'+yearValue;
		for (v in this.settings.validators) {
			if (!this.settings.validators[v].validate(dateString)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[v].errMsg+' '));
				errors = errors + 1;
			}
		}
		if (errors < 1)	return true;
		else {
			this.formObject
			while (this.formObj.bubbleText.firstChild)  this.formObj.bubbleText.removeChild(this.formObj.bubbleText.firstChild);
			
			this.formObj.bubbleText.appendChild(errorMsgs);
			
		
			return false;
		}
	},
	goValidate: function () {
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonDay');
		var caption = document.getElementById ('caption_'+this.settings.ref);
		
		thisForm = this.formObj;
		var makeInvisible = function () {
			thisForm.bubble.style.visibility = 'hidden';
			thisForm.gui.bubbleFocus = null;
		}
		if (this.validate()) {
			this.formObj.setValidates(true);
			if (this.formObj.gui.bubbleFocus == this.settings.ref) {
				

				this.formObj.fader.fadeTo(0,10, makeInvisible);	
				
			}
			if (element.value) this.changeStatus('valid');
			caption.className = 'caption';
			return true;
		} else {
			this.formObj.setValidates(false);
			this.changeStatus('notValid');
			element.className = this.className+'_notValid';
			caption.className = 'caption_notValid';
			
			if (this.formObj.gui.bubbleFocus != this.settings.ref) {
				
				this.formObj.gui.bubbleFocus = this.settings.ref;
				this.formObj.bubble.style.top = String(this.formObj.gui.topOffset+ caption.offsetTop+13)+ 'px';
				
				this.formObj.bubble.style.visibility = 'visible';
				this.formObj.fader.fadeTo(90,10, false);	
				var cRef = this.settings.ref;
				var fObj = this.formObj;
				var fn = function () {
					if (fObj.gui.bubbleFocus == cRef){
						fObj.fader.fadeTo(0,10, makeInvisible);
					}	
				}
				window.setTimeout(fn,6000);
				
			
			
			}
		return false;
		}
		
	},
	updateValue: function (value) {
	
		var element_day = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonDay');
		var element_month = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonMonth');
		var element_year = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonYear');
		if(!element_year){
				var thisLoc = this;
				var fn = function () {
					thisLoc.updateValue(value);
				}
				window.setTimeout(fn,100);
				return;
		}
		var curdate = new Date();
		currentYear = curdate.getFullYear();
		var date_split = value.split('-');
		var year = currentYear - date_split[0] + 1;
		var month = date_split[1] - 1;
		var day = date_split[2];
		this.settings.value = value;
		element_day.options[day].selected = true;
		element_month.options[month].selected = true;
		element_year.options[year].selected = true;
	},
	elemOnBlur: function () {
		
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className;
		this.goValidate ();
	}
});

 


var FileElement = jj.def ('FileElement', AbstractElement, {

	FileElement: function (settings) {
		this.AbstractElement (settings);
		this.className = 'inputText';
	},

	returnInput: function () {
		
		var inputButton = jj.createNamedElement( 'input', this.settings.ref );
		inputButton.id = this.settings.ref;
		inputButton.type = 'file';
		inputButton.className = this.className;
	
		return inputButton;
				
	},

	elemOnFocus: function () {
		
		var element = document.getElementById (this.settings.ref);
		
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},

	elemOnBlur: function () {
		
		var element = document.getElementById (this.settings.ref);
		
		element.className = this.className;
		this.goValidate ();
	}
});

 


var LocationElement = jj.def ('LocationElement', AbstractElement, {

	LocationElement: function (settings) {
		this.options = settings.options;
		this.AbstractElement (settings);
		this.className = 'inputSelect';
		
		this.getCountries();
	},
	getCountries: function() {
	
		var jjax = new Jjax ();
		var thisobj = this;
		var jjaxHandler = {
			onSuccess: function (response) {
				
				try {
					thisobj.popCountries(response.responseText);
				} catch (e) {
					flare.sparkle.addDebug("error", "location element caught error: "+e.message);
				}
			},
			onFailure: function (response) {
				alert(response.responseText);
			}
		};
		jjax.simplePost ('/data/geo/lookup.php?getCountries=1', 'application/x-www-form-urlencoded', 'test=true', jjaxHandler);
	},
	getGegionData: function(region_id, city_id) {
	
		var jjax = new Jjax ();
		var thisobj = this;
		var jjaxHandler = {
			onSuccess: function (response) {
				return response.responseText;
			},
			onFailure: function (response) {
				alert(response.responseText);
			}
		};
		jjax.simplePost ('/data/geo/lookup.php?reg_id='+region_id+'&city_id='+city_id, 'application/x-www-form-urlencoded', 'test=true', jjaxHandler);
	},
	popCountries: function(country_string) {
	
	
		
		var country_array = jjax.fromJson (country_string);
		
		var countrySelectObject = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry');
				
				var option = jj.createNamedElement( 'option', 'noCountry' );
				option.appendChild(document.createTextNode("-- Select Country --"));
				countrySelectObject.appendChild(option);
				delete option;
		
		
		for (i in country_array) {
			
				var option = document.createElement('option');
				
				option.value = country_array [i] [0];
				
				option.appendChild(document.createTextNode(country_array[i] [1]));
				countrySelectObject.appendChild(option);
				delete option;
			
		}
	},
	getRegions: function(country) {
	
		var jjax = new Jjax ();
		var thisobj = this;
		var jjaxHandler = {
			onSuccess: function (response) {
				try {
					if(response.responseText != ''){
						thisobj.popRegions(response.responseText);
					}
				} catch (e) {
					flare.sparkle.addDebug("error", "location element caught error: "+e.message);					
				}
			},
			onFailure: function (response) {
				alert(response.responseText);
			}
		};
		jjax.simplePost ('/data/geo/lookup.php?getRegions='+country, 'application/x-www-form-urlencoded', 'test=true', jjaxHandler);
	},
	getCities: function(region_id) {
	
		var jjax = new Jjax ();
		var thisobj = this;
		var jjaxHandler = {
			onSuccess: function (response) {
				try {
					if(response.responseText != ''){
						thisobj.popCity(response.responseText);
					}
				} catch (e) {
					flare.sparkle.addDebug("error", "location element caught error: "+e.message);					
				}
			},
			onFailure: function (response) {
				alert(response.responseText);
			}
		};
		jjax.simplePost ('/data/geo/lookup.php?getCitys='+region_id, 'application/x-www-form-urlencoded', 'test=true', jjaxHandler);
	},
	popRegions: function(country_string) {
	
	
		var region_array = country_string.split('|');
		
		var regionSelectObject = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_inputButtonState');
		
		if (region_array.length != 3){
				var option = jj.createNamedElement( 'option', region_array[1] );
				option.appendChild(document.createTextNode("-- Select Region --"));
				regionSelectObject.appendChild(option);
				delete option;
				regionSelectObject.disabled = false;
		}else {
				var option = jj.createNamedElement( 'option', region_array[1] );
				option.appendChild(document.createTextNode("-- No Regions --"));
				regionSelectObject.appendChild(option);
				delete option;
		}
		for (i = 0; i < region_array.length; i = i + 2){
			if (region_array[i]  && region_array[i] != -1){
				regionSelectObject.appendChild(this.createOption(region_array[i],region_array[i+1]));
			}
		}
	},
	popCity: function(region_string) {
	
	
		region_string = '-- Select City --|'+ region_string;
		var city_array = region_string.split('|');
		
		var citySelectObject = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_inputButtonCity');
		citySelectObject.disabled = false;
		for (i=1; i < city_array.length; i=i+2){
			if (city_array[i]  && city_array[i] != -1){
				citySelectObject.appendChild(this.createOption(city_array[i],city_array[i+1]));
			}
		}
	},
	createOption: function(in_name, in_id) {
	
		var option = jj.createNamedElement( 'option', in_id );
		option.value = in_id;
		option.appendChild(document.createTextNode(in_name));
		return option;
	},
	
	returnInput: function () {
		
		var docFrag = document.createDocumentFragment();
		var thisobj = this;
		
		var inputButtonCountry =  jj.createNamedElement( 'select', this.settings.ref );
		inputButtonCountry.id = this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry';
		inputButtonCountry.className = this.className;
		inputButtonCountry.onchange = function(){
			inputButtonState.disabled = true;
			inputButtonCity.disabled = true;
			inputButtonState.innerHTML = '';
			inputButtonCity.innerHTML = '';
			destination = inputButtonCountry.options[inputButtonCountry.selectedIndex].value;
			thisobj.getRegions(destination);
		};

		var inputButtonState = document.createElement('select');
		inputButtonState.id = this.formObj.formName+'_'+this.settings.ref+'_inputButtonState';
		
		inputButtonState.className = this.className;
		inputButtonState.disabled = true;
		inputButtonState.onchange = function(){
			inputButtonCity.innerHTML = '';
			destination = inputButtonState.options[inputButtonState.selectedIndex].value;
			thisobj.getCities(destination);
		};
		
		var inputButtonCity = document.createElement('select');
		inputButtonCity.id = this.formObj.formName+'_'+this.settings.ref+'_inputButtonCity';
		inputButtonCity.className = this.className;
		inputButtonCity.disabled = true;
		
		docFrag.appendChild(inputButtonCountry);
		docFrag.appendChild(inputButtonState);
		docFrag.appendChild(inputButtonCity);

		return docFrag;
				
	},

	elemOnFocus: function () {
		
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},
	returnValueArr: function () {
		var countryDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry');
		var countryValue = countryDom.options[countryDom.selectedIndex].value;
		if (!countryValue) countryValue = null;
		var stateDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_inputButtonState');
		var stateValue;
		if (stateDom.selectedIndex > -1){
			var stateValue = stateDom.options[stateDom.selectedIndex].value;
		}
		if (!stateValue || isNaN(stateValue)) stateValue = null;
		var cityDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_inputButtonCity');
		var cityValue;
		if (cityDom.selectedIndex > -1){
			var cityValue = cityDom.options[cityDom.selectedIndex].name;
		}
		if (!cityValue) cityValue = null;
		return [ this.settings.ref, {
			countryId: countryValue? Number (countryValue) : undefined,
			regionId: stateValue? Number (stateValue) : undefined,
			cityId: cityValue? Number (cityValue) : undefined
		} ];
	},
	validate: function () {
		if (!this.settings.validators) return true;
		
		if (this.settings.validators.length < 1) return true;
		
		var errorMsgs = document.createDocumentFragment();
		var errors = 0;
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry');
		var element2 = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_inputButtonState');
		var element3 = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_inputButtonCity');
		if (!this.settings.validators[0].validate(element.value)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[0].errMsg+' '));
				errors = errors + 1;
		}
		if (!this.settings.validators[1].validate(element2.value)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[1].errMsg+' '));
				errors = errors + 1;
		}
		if (!this.settings.validators[2].validate(element3.value)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[2].errMsg+' '));
				errors = errors + 1;
		}
		if (errors < 1)	return true;
		else {
			this.formObject
			while (this.formObj.bubbleText.firstChild)  this.formObj.bubbleText.removeChild(this.formObj.bubbleText.firstChild);
			
			this.formObj.bubbleText.appendChild(errorMsgs);
			
		
			return false;
		}
	},
	goValidate: function () {
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry');
		var caption = document.getElementById ('caption_'+this.settings.ref);
		
		thisForm = this.formObj;
		var makeInvisible = function () {
			thisForm.bubble.style.visibility = 'hidden';
			thisForm.gui.bubbleFocus = null;
		}
		if (this.validate()) {
			this.formObj.setValidates(true);
			if (this.formObj.gui.bubbleFocus == this.settings.ref) {
				

				this.formObj.fader.fadeTo(0,10, makeInvisible);	
				
			}
			if (element.value) this.changeStatus('valid');
			caption.className = 'caption';
			return true;
		} else {
			this.formObj.setValidates(false);
			this.changeStatus('notValid');
			element.className = this.className+'_notValid';
			caption.className = 'caption_notValid';
			
			if (this.formObj.gui.bubbleFocus != this.settings.ref) {
				
				this.formObj.gui.bubbleFocus = this.settings.ref;
				this.formObj.bubble.style.top = String(this.formObj.gui.topOffset+ caption.offsetTop+13)+ 'px';
				
				this.formObj.bubble.style.visibility = 'visible';
				this.formObj.fader.fadeTo(90,10, false);	
				var cRef = this.settings.ref;
				var fObj = this.formObj;
				var fn = function () {
					if (fObj.gui.bubbleFocus == cRef){
						fObj.fader.fadeTo(0,10, makeInvisible);
					}	
				}
				window.setTimeout(fn,6000);
				
			
			
			}
		return false;
		}
		
	},	
	setSelected: function (in_string, in_element) {
		
		
		if(!in_element.length){
				var thisLoc = this;
				var fn = function () {
					thisLoc.setSelected(in_string, in_element);
				}
				window.setTimeout(fn,50);
				return;
		}
		for (var i=0; i<in_element.length; i++) {
			if(!in_element[i]){
				var thisLoc = this;
				var fn = function () {
					thisLoc.setSelected(in_string, in_element);
				}
				window.setTimeout(fn,50);
				return;
			}
			if(in_element[i].value == in_string){
				in_element[i].selected = true;
			}
		}
	},
	setSelect: function (in_value) {
		var current_element = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry');
		var current_element2 = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_inputButtonState');
		var current_element3 = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_inputButtonCity');
		thisLoc = this;
		if(!current_element || !current_element2 || !current_element3){
			
			
			var fn = function () {
				thisLoc.setSelect(in_value);
			}
			window.setTimeout(fn,50);
			return;
		}
		this.getRegions(in_value[0]);
		if(in_value[1] && in_value[1] != 'undefined')this.getCities(in_value[1]);
		
		
		this.setSelected(in_value[0],current_element);
		if(in_value[1] && in_value[1] != 'undefined'){
			this.setSelected(in_value[1],current_element2);
			if(in_value[2] && in_value[2] != 'undefined'){
				this.setSelected(in_value[2],current_element3);
			}
		}
	},
	updateValue: function (values) {
		this.setSelect(values);
	},
	elemOnBlur: function () {
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		element.className = this.className;
		this.goValidate ();
	}
});

 


var LocationSearchElement = jj.def ('LocationSearchElement', LocationElement, {

	LocationSearchElement: function (settings) {
		this.options = settings.options;
		this.AbstractElement (settings);
		this.className = 'inputSelect';
		
		this.getCountries();
	},
	popCountries: function(country_string) {
	
	
		
		var country_array = jjax.fromJson (country_string);
		
		var countrySelectObject = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry');
				
				var option = jj.createNamedElement( 'option', 'noCountry' );
				option.appendChild(document.createTextNode("-- Select Country --"));
				countrySelectObject.appendChild(option);
				delete option;
		
		
		for (i in country_array) {
			
				var option = document.createElement('option');
				
				option.value = country_array [i] [0];
				
				option.appendChild(document.createTextNode(country_array[i] [1]));
				countrySelectObject.appendChild(option);
				delete option;
			
		}
	},
	popCity: function(region_string) {
	
	
		region_string = '-- Select City --|'+ region_string;
		var city_array = region_string.split('|');
		
		var citySelectObject = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_inputButtonCity');
				
				var option = jj.createNamedElement( 'option', 'noCity' );
				option.appendChild(document.createTextNode("-- Select City --"));
				citySelectObject.appendChild(option);
				delete option;

		citySelectObject.disabled = false;
		for (i=1; i < city_array.length; i=i+2){
			if (city_array[i]  && city_array[i] != -1){
				citySelectObject.appendChild(this.createOption(city_array[i],city_array[i+1]));
			}
		}
	},
	validate: function () {
		if (!this.settings.validators) return true;
		
		if (this.settings.validators.length < 1) return true;
		
		var errorMsgs = document.createDocumentFragment();
		var errors = 0;
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry');
		var element2 = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_inputButtonState');
		var element3 = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_inputButtonCity');
		if (this.settings.validators[0] && !this.settings.validators[0].validate(element.value)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[0].errMsg+' '));
				errors = errors + 1;
		}
		if (this.settings.validators[1] &&!this.settings.validators[1].validate(element2.value)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[1].errMsg+' '));
				errors = errors + 1;
		}
		if (this.settings.validators[2] &&!this.settings.validators[2].validate(element3.value)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[2].errMsg+' '));
				errors = errors + 1;
		}
		if (errors < 1)	return true;
		else {
			this.formObject
			while (this.formObj.bubbleText.firstChild)  this.formObj.bubbleText.removeChild(this.formObj.bubbleText.firstChild);
			
			this.formObj.bubbleText.appendChild(errorMsgs);
			
		
			return false;
		}
	},
	goValidate: function () {
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_InputButtonCountry');
		var caption = document.getElementById ('caption_'+this.settings.ref);
		
		thisForm = this.formObj;
		var makeInvisible = function () {
			thisForm.bubble.style.visibility = 'hidden';
			thisForm.gui.bubbleFocus = null;
		}
		if (this.validate()) {
			this.formObj.setValidates(true);
			if (this.formObj.gui.bubbleFocus == this.settings.ref) {
				

				this.formObj.fader.fadeTo(0,10, makeInvisible);	
				
			}
			if (element.value) this.changeStatus('valid');
			caption.className = 'caption';
			return true;
		} else {
			this.formObj.setValidates(false);
			this.changeStatus('notValid');
			element.className = this.className+'_notValid';
			caption.className = 'caption_notValid';
			
			if (this.formObj.gui.bubbleFocus != this.settings.ref) {
				
				this.formObj.gui.bubbleFocus = this.settings.ref;
				this.formObj.bubble.style.top = String(this.formObj.gui.topOffset+ caption.offsetTop+13)+ 'px';
				
				this.formObj.bubble.style.visibility = 'visible';
				this.formObj.fader.fadeTo(90,10, false);	
				var cRef = this.settings.ref;
				var fObj = this.formObj;
				var fn = function () {
					if (fObj.gui.bubbleFocus == cRef){
						fObj.fader.fadeTo(0,10, makeInvisible);
					}	
				}
				window.setTimeout(fn,6000);
				
			
			
			}
		return false;
		}
		
	}
});

 


var TextElement = jj.def ('TextElement', AbstractElement, {

	TextElement: function (settings) {
		this.AbstractElement (settings);
		this.className = 'inputText';
	},
	returnInput: function () {
		
		var inputButton = document.createElement('input');
		inputButton.name = this.settings.ref;
		inputButton.id = this.formObj.formName+'_'+this.settings.ref;
		inputButton.type = 'text';
		inputButton.className = this.className;
		if (this.settings.value) inputButton.value = this.settings.value;
		var thisInput = this;
		inputButton.onchange = jj.bind(this.formObj,'elementChanged');
		inputButton.onfocus  = function() { thisInput.elemOnFocus(); }
		inputButton.onblur  = function() { thisInput.elemOnBlur(); }
		
		
		return inputButton;		
	},
	elemOnFocus: function () {
		this.changeStatus('focus');
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},
	elemOnBlur: function () {
	
		this.changeStatus('blur');
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className;
		this.goValidate ();
	}
});

 


var PasswordElement = jj.def ('PasswordElement', TextElement, {

	PasswordElement: function (settings) {
		this.TextElement (settings);
	},

	returnInput: function () {
		var inputButton = jj.createNamedElement( 'input', this.settings.ref );
		inputButton.id = this.formObj.formName+'_'+this.settings.ref;
		inputButton.type = 'password';
		inputButton.className = 'inputText';
		if (this.settings.value) inputButton.value = this.settings.value;
	

		var thisInput = this;
		inputButton.onchange = jj.bind(this.formObj,'elementChanged');
		inputButton.onfocus  = function() { thisInput.elemOnFocus(); }
		inputButton.onblur  = function() { thisInput.elemOnBlur(); }
		
		return inputButton;
	}
});

 


var RadioTableElement = jj.def ('RadioTableElement', AbstractElement, {

	RadioTableElement: function (settings) {
		this.options = settings.options;
		this.AbstractElement (settings);
		this.className = 'inputTickBox';
	},
	returnCaption: function () {
		if (!this.settings.caption) return false;
		var element = document.createElement('div');
		element.innerHTML = this.settings.caption;
		return element;
	},
	returnInput: function () {
		
		var table = document.createElement('table');	
		table.style.width = '100%';	

		
		var tbody = document.createElement( 'tbody' );
		tbody.id = 'tickTable';
		
		table.appendChild( tbody );
		
		
		for (i in this.options) {
			var row = document.createElement('tr');
			var cell1 = document.createElement('td');
			
			var option = document.createElement('input');
			option.id = this.options[i][0];
			option.name = this.options[i][0];
			option.type = 'radio';
			option.name = 'random';
			option.className = this.className;
			option.style.borderWidth = '0px';

			
			var optionLabel = document.createElement('label');
			optionLabel.htmlFor = this.options[i][0];
			optionLabel.appendChild(document.createTextNode(this.options[i][1]));
			
			cell1.appendChild(option);
			cell1.appendChild(optionLabel);
			row.appendChild(cell1);
			tbody.appendChild(row);
			delete option;
			delete optionLabel;
			delete row;
			delete cell1;
			
		}
		
		if (i%2==0) {
			row.appendChild(document.createElement('td'));
			tbody.appendChild(row);
		}
	
		return table;
				
	},
	postRender: function () {
		

	},
	returnValueArr: function () {
		
		var returnArr = {};
		var checkValue = false;
		for (i in this.options) {
			checkValue = false;
			if (document.getElementById(this.options[i][0]).checked) checkValue = true;
			returnArr[this.options[i][0]] = checkValue;
		}
		return [this.settings.ref,returnArr];
		
		
	},
	updateValue: function (values) {
		this.settings.value = values;	
		for (i in this.options) {	
			if (values[this.options[i][0]]) document.getElementById(this.options[i][0]).checked = true;
		}		
	},
	goValidate: function () {
return true;
		
	},
	
	validate: function () {
return true;
	},
	elemOnFocus: function () {
		
		var element = document.getElementById (this.settings.ref);
		
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},

	elemOnBlur: function () {
		
		var element = document.getElementById (this.settings.ref);
		
		element.className = this.className;
		this.goValidate ();
	}
});

 


var SelectElement = jj.def ('SelectElement', AbstractElement, {

	SelectElement: function (settings) {
		this.options = settings.options;
		this.AbstractElement (settings);
		this.className = 'inputSelect';
	},

	returnInput: function () {
		
		var inputButton = jj.createNamedElement( 'select',this.settings.ref );
		inputButton.id = this.formObj.formName+'_'+this.settings.ref;
		inputButton.className = this.className;
		var index = 0;
		this.indexArr = new Array();
		this.indexMap = {};
		
		for (i in this.options) {
			this.indexArr[index] = this.options[i][0];
			this.indexMap[this.options[i][0]] = index;
			
			var option = jj.createNamedElement( 'option', this.options[i][0] );
			option.appendChild(document.createTextNode(this.options[i][1]));
			inputButton.appendChild(option);
			delete option;
			
			index = index +1;
		}
		
	
		return inputButton;
				
	},

	elemOnFocus: function () {
		
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},
	returnValueArr: function () {
		return [this.settings.ref,this.options[Number(document.getElementById(this.formObj.formName+'_'+this.settings.ref).selectedIndex)][0]];
		
		
	},
	updateValue: function (value) {

		this.settings.value = value;

		var element = document.getElementById(this.formObj.formName+'_'+this.settings.ref);
		if (element.options[this.indexMap[value]]) element.selectedIndex = this.indexMap[value];
		else {
			flare.sparkle.addDebug('error','Error in form: '+this.formObj.formName+', SELECT element (dom id: '+this.formObj.formName+'_'+this.settings.ref+') has no option '+this.indexMap[value]+' code: '+value);
		}
	},
	elemOnBlur: function () {
		
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className;
		this.goValidate ();
	}
});

 


var TextAreaElement = jj.def ('TextAreaElement', AbstractElement, {

	TextAreaElement: function (settings) {
		this.AbstractElement (settings);
		this.className = 'inputTextArea';
	},

	returnInput: function () {
		
		var inputButton = document.createElement('textarea');
		inputButton.name = this.settings.ref;
		inputButton.id = this.formObj.formName+'_'+this.settings.ref;
		inputButton.className = this.className;
		
		if (this.settings.height) inputButton.style.height = this.settings.height;
		
		if (this.settings.value) inputButton.appendChild(document.createTextNode(this.settings.value));
		var thisInput = this;
		inputButton.onchange = jj.bind(this.formObj,'elementChanged');
		inputButton.onfocus  = function() { thisInput.elemOnFocus(); }
		inputButton.onblur  = function() { thisInput.elemOnBlur(); }
		
		return inputButton;
				
	},
	updateValue: function (value) {
		
		this.settings.value = value;
		var element = document.getElementById(this.formObj.formName+'_'+this.settings.ref);
		while (element.firstChild) element.removeChild(element.firstChild);
		element.appendChild(document.createTextNode(this.settings.value));
		
	},
	elemOnFocus: function () {
		
		this.changeStatus('focus');
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},

	elemOnBlur: function () {
		
		this.changeStatus('focus');
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className;
		this.goValidate ();
	}
});

 


var TickTableElement = jj.def ('TickTableElement', AbstractElement, {

	TickTableElement: function (settings) {
		this.options = settings.options;
		this.AbstractElement (settings);
		this.className = 'inputTickBox';
	},

	returnInput: function () {
		
		var table = document.createElement('table');	
		table.style.width = '100%';	

		
		var tbody = document.createElement( 'tbody' );
		tbody.id = 'tickTable';
		
		table.appendChild( tbody );
		
		
		for (i in this.options) {
			if (i%2==0) var row = document.createElement('tr');
			var cell1 = document.createElement('td');
			
			var option = document.createElement('input');
			option.id = this.options[i][0];
			option.name = this.options[i][0];
			option.type = 'checkbox';
			option.className = this.className;
			option.style.borderWidth = '0px';

			
			var optionLabel = document.createElement('label');
			optionLabel.htmlFor = this.options[i][0];
			optionLabel.appendChild(document.createTextNode(this.options[i][1]));
			
			cell1.appendChild(option);
			cell1.appendChild(optionLabel);
			row.appendChild(cell1);
			if (i%2)tbody.appendChild(row);
			delete option;
			delete optionLabel;
			if (i%2) delete row;
			delete cell1;
			
		}
		
		if (i%2==0) {
			row.appendChild(document.createElement('td'));
			tbody.appendChild(row);
		}
	
		return table;
				
	},
	postRender: function () {
		

	},
	returnValueArr: function () {
		
		var returnArr = {};
		var checkValue = false;
		for (i in this.options) {
			checkValue = false;
			if (document.getElementById(this.options[i][0]).checked) checkValue = true;
			returnArr[this.options[i][0]] = checkValue;
		}
		return [this.settings.ref,returnArr];
		
		
	},
	updateValue: function (values) {
		this.settings.value = values;	
		for (i in this.options) {	
			if (values[this.options[i][0]]) document.getElementById(this.options[i][0]).checked = true;
		}		
	},
	goValidate: function () {
return true;
		
	},
	
	validate: function () {
return true;
	},
	elemOnFocus: function () {
		
		var element = document.getElementById (this.settings.ref);
		
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},

	elemOnBlur: function () {
		
		var element = document.getElementById (this.settings.ref);
		
		element.className = this.className;
		this.goValidate ();
	}
});

 


var TsandCsElement = jj.def ('TsandCsElement', AbstractElement, {

	TsandCsElement: function (settings) {
		this.AbstractElement (settings);
		this.className = 'inputTextArea';
	},

	returnInput: function () {
		var docFrag = document.createDocumentFragment();
		var inputButton = document.createElement('div');
		inputButton.style.overflow = 'scroll';
		inputButton.style.overflowY = 'scroll';
		inputButton.style.overflowX = 'hidden';
		
		inputButton.style.height = '150px';
		inputButton.style.marginBottom = '5px';
		
		inputButton.name = this.settings.ref;
		inputButton.id = this.formObj.formName+'_'+this.settings.ref;
		inputButton.className = this.className;
		
		if (this.settings.height) inputButton.style.height = this.settings.height;
		
		if (this.settings.value) inputButton.appendChild(document.createTextNode(this.settings.value));
		var thisInput = this;
		inputButton.onchange = jj.bind(this.formObj,'elementChanged');
		
		inputButton.onfocus  = function() { inputButton.blur()}
		inputButton.style.fontSize = "10px";
		inputButton.innerHTML = this.settings.bodyText;
		var acceptTandC = document.createTextNode(' I agree to the above');
		var inputCheckbox = document.createElement('input');
		inputCheckbox.type = 'checkbox';
		inputCheckbox.id = this.formObj.formName+'_'+this.settings.ref+'_inputCheckbox';
		docFrag.appendChild(inputButton);
		docFrag.appendChild(inputCheckbox);
		docFrag.appendChild(acceptTandC);
		
		return docFrag;
				
	},
	updateValue: function (value) {
		
		this.settings.value = value;
		var element = document.getElementById(this.formObj.formName+'_'+this.settings.ref);
		while (element.firstChild) element.removeChild(element.firstChild);
		element.appendChild(document.createTextNode(this.settings.value));
		
	},
	returnValueArr: function () {
		
		
		
		var termsDom = document.getElementById(this.formObj.formName+'_'+this.settings.ref+'_inputCheckbox');
		var termsValue = termsDom.checked;
		
		return [this.settings.ref,termsValue];
		
	},
	validate: function () {
		if (!this.settings.validators) return true;
		
		var errorMsgs = document.createDocumentFragment();
		var errors = 0;
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_inputCheckbox');
		var termsValue = element.checked;
		for (v in this.settings.validators) {
			if (!this.settings.validators[v].validate(termsValue)) {
				errorMsgs.appendChild(document.createTextNode(this.settings.validators[v].errMsg+' '));
				errors = errors + 1;
			}
		}
		if (errors < 1)	return true;
		else {
			this.formObject
			while (this.formObj.bubbleText.firstChild)  this.formObj.bubbleText.removeChild(this.formObj.bubbleText.firstChild);
			
			this.formObj.bubbleText.appendChild(errorMsgs);
			
		
			return false;
		}
	},
	goValidate: function () {
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref+'_inputCheckbox');
		var caption = document.getElementById ('caption_'+this.settings.ref);
		
		thisForm = this.formObj;
		var makeInvisible = function () {
			thisForm.bubble.style.visibility = 'hidden';
			thisForm.gui.bubbleFocus = null;
		}
		if (this.validate()) {
			this.formObj.setValidates(true);
			if (this.formObj.gui.bubbleFocus == this.settings.ref) {
				

				this.formObj.fader.fadeTo(0,10, makeInvisible);	
				
			}
			if (element.value) this.changeStatus('valid');
			caption.className = 'caption';
			return true;
		} else {
			this.formObj.setValidates(false);
			this.changeStatus('notValid');
			element.className = this.className+'_notValid';
			caption.className = 'caption_notValid';
			
			if (this.formObj.gui.bubbleFocus != this.settings.ref) {
				
				this.formObj.gui.bubbleFocus = this.settings.ref;
				this.formObj.bubble.style.top = String(this.formObj.gui.topOffset+ caption.offsetTop+13)+ 'px';
				
				this.formObj.bubble.style.visibility = 'visible';
				this.formObj.fader.fadeTo(90,10, false);	
				var cRef = this.settings.ref;
				var fObj = this.formObj;
				var fn = function () {
					if (fObj.gui.bubbleFocus == cRef){
						fObj.fader.fadeTo(0,10, makeInvisible);
					}	
				}
				window.setTimeout(fn,6000);
				
			
			
			}
		return false;
		}
		
	},
	elemOnFocus: function () {
		
		this.changeStatus('focus');
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className+'_focus';
		var caption = document.getElementById ('caption_'+this.settings.ref);
		caption.className = 'caption';
	},

	elemOnBlur: function () {
		
		this.changeStatus('focus');
		var element = document.getElementById (this.formObj.formName+'_'+this.settings.ref);
		
		element.className = this.className;
		this.goValidate ();
	}
});

 
function ValidateAge(param) {

	
	this.errMsg = 'You must be over 18 to enter this site.';
	
} 

ValidateAge.prototype.validate = function (inData) {
	var then = new Date ();
	then.setYear (then.getYear () - 18);
	return jj.toYmd (new Date (inData)) <= jj.toYmd (then);
}

 
function ValidateAgeRange (param) {

	
	this.errMsg = 'You must select a .';
	
} 

ValidateAgeRange.prototype.validate = function (inData) {
	
	if (inData[0] <= inData[1]) return true; 
	
	 return false;		
}

 
function ValidateCity (param) {

	
	this.errMsg = 'You have not choosen a city.';
	
} 

ValidateCity.prototype.validate = function (inData) {
	
	if (inData != '-- Select City --') return true;
	
	 return false;
	
	
}

 
function ValidateCountry (param) {

	
	this.errMsg = 'You have not choosen a country.';
	
} 

ValidateCountry.prototype.validate = function (inData) {
	
	if (inData != '-- Select Country --') return true;
	
	 return false;
	
	
}

 
function ValidateDate(param) {

	
	this.errMsg = 'Please choose a valid date.';
	
} 

ValidateDate.prototype.validate = function (inData) {
	
	if (isValidDate(inData)) return true;
	
	return false;
	
	
}

function isValidDate(dateStr) {




var datePat = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{2}|\d{4})$/;




var matchArray = dateStr.match(datePat); 
if (matchArray == null) {

return false;
}
month = matchArray[1]; 
day = matchArray[3];
year = matchArray[4];
if (month < 1 || month > 12) { 

return false;
}
if (day < 1 || day > 31) {

return false;
}
if ((month==4 || month==6 || month==9 || month==11) && day==31) {

return false
}
if (month == 2) { 
var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
if (day>29 || (day==29 && !isleap)) {

return false;
   }
}
return true;  
}

 
function ValidateEmail (param) {

	
	this.errMsg = 'You have not entered a valid Email Address.';
	
} 

ValidateEmail.prototype.validate = function (inData) {
	
	var filter  = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	if (inData.length == 0 || filter.test(inData)) return true;
	
	 return false;
	
	
}

 
function ValidateEmailConfirm (email_1) {
	
	this.errMsg = 'Doesn\'t match email above';
	this.email1 = email_1;
}

ValidateEmailConfirm.prototype.validate = function (inData) {
	
	element = document.getElementById(this.email1);
	email2 = element.value;
	if(email2 != inData) return false;
	return true;
}
 
function ValidateMaxChars (maxChars) {
	this.maxChars = maxChars;
	
	this.errMsg = 'You must enter less than '+maxChars+' characters.';
} 

ValidateMaxChars.prototype.validate = function (inData) {
	
	if (inData.length > this.maxChars && inData.length > 0) return false;
	return true;
	
}

 
function ValidateMaxWords (maxWords) {
	this.maxWords = maxWords;
	
	this.errMsg = 'You must enter at least '+maxWords+' words.';
} 

ValidateMaxWords.prototype.validate = function (inData) {
	var count = String (inData).split(" ");
	if (count.length > this.maxWords && inData.length > 0) return false;
	
	return true;
	
}

 
function ValidateMinChars (minChars) {
	this.minChars = minChars;
	
	this.errMsg = 'You must enter at least '+minChars+' characters.';
} 

ValidateMinChars.prototype.validate = function (inData) {
	
	if (inData.length < this.minChars && inData.length > 0) return false;
	
	return true;
	
}






 
function ValidateMinWords (minWords) {
	this.minWords = minWords;
	
	this.errMsg = 'You must enter at least '+minWords+' words.';
} 

ValidateMinWords.prototype.validate = function (inData) {
	var count = String (inData).split(" ");
	if (count.length < this.minWords && inData.length > 0) return false;
	
	return true;
	
}

 
function ValidatePasswordConfirm (new_password_1) {
	
	this.errMsg = 'Doesn\'t match password above';
	this.newPassword1 = new_password_1;
}

ValidatePasswordConfirm.prototype.validate = function (inData) {
	
	element = document.getElementById(this.newPassword1);
	newPassword = element.value;
	if(newPassword != inData) return false;
	return true;
}
 
function ValidatePhoneNumber (maxChars) {
	this.maxChars = maxChars;
	
	this.errMsg = 'Number must be 11 digits long and begin with a 0.';
} 

ValidatePhoneNumber.prototype.validate = function (inData) {
	
	if (inData.length > 11){
		return false;	
	}else if (inData.charAt(0) != '0'){
		return false;
	}else
		return true;
	
}

 
function ValidateRegion(param) {

	
	this.errMsg = 'You have not choosen a region.';
	
} 

ValidateRegion.prototype.validate = function (inData) {
	
	if (inData != '-- Select Region --') return true;
	
	 return false;
	
	
}

 
function ValidateRequired () {
	
	this.errMsg = 'This is a required field.';
} 

ValidateRequired.prototype.validate = function (inData) {
	
	if (!inData.length) return false;
	return true;
}

 
function ValidateSelection (param) {

	
	this.errMsg = 'Please select where you heard about us.';
	
} 

ValidateSelection.prototype.validate = function (inData) {
	
	if (inData != '-- Please Select --') return true;
	
	 return false;
	
	
}

 
function ValidateTandC (param) {

	
	this.errMsg = 'You must agree to the terms and conditions.';
	
} 

ValidateTandC.prototype.validate = function (inData) {
	
	if (inData) return true;
	
	 return false;
	
	
}

 
function ValidateUserPassword () {
	
	this.errMsg = 'Must be the same as your current password';
} 

ValidateUserPassword.prototype.validate = function (inData) {
	var current_pass = flare.sparkle.userCore.passwordHash;
	var submittedPass = MD5(inData);
	if (current_pass != submittedPass) return false;
	return true;
}

var MD5 = function (password) {
		var passwordUtf8 = utf8.encode (password);
		return md5.binl2hex (md5.hash (md5.str2binl (passwordUtf8, 8), 8 * passwordUtf8.length));
}
 







function getCookie( name ) {
var start = document.cookie.indexOf( name + "=" );
var len = start + name.length + 1;
if ( ( !start ) &&
( name != document.cookie.substring( 0, name.length ) ) )
{
return null; 
} 
if ( start == -1 ) return null; 
var end = document.cookie.indexOf( ";", len ); 
if ( end == -1 ) end = document.cookie.length; 
return unescape( document.cookie.substring( len, end ) ); 
} 
function simplePopup(URL) { 
		day = new Date(); 
		id = day.getTime(); 
		eval("page" + id + " = window.open(URL, \'" + id + "\', \'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=510,height=645\');"); 
}
function setCookie( name, value, expires, path, domain, secure ) 
{

var today = new Date();
today.setTime( today.getTime() );


if ( expires )
{
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date( today.getTime() + (expires) );

document.cookie = name + "=" +escape( value ) +
( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) + 
( ( path ) ? ";path=" + path : "" ) + 
( ( domain ) ? ";domain=" + domain : "" ) +
( ( secure ) ? ";secure" : "" );
}

function deleteCookie( name, path, domain ) {
if ( getCookie( name ) ) document.cookie = name + "=" +
( ( path ) ? ";path=" + path : "") +
( ( domain ) ? ";domain=" + domain : "" ) +
";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}

function formMessage( thismessage ) {
	var centralPanel = document.getElementById("bodyContentContainer");
	var message = document.createElement('div');
	message.className = "formAlertMessage";
	message.appendChild(document.createTextNode(thismessage));
	centralPanel.insertBefore(message,centralPanel.childNodes[2]);
}

function MD5 (password) {
	var passwordUtf8 = utf8.encode (password);
	return md5.binl2hex (md5.hash (md5.str2binl (passwordUtf8, 8), 8 * passwordUtf8.length));
}
 

