

/*  Prototype JavaScript framework
 *  (c) 2005 Sam Stephenson <sam@conio.net>
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://prototype.conio.net/
/*--------------------------------------------------------------------------*/

//note: modified & stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net).

var Class = {
	create: function() {
		return function() {
			this.initialize.apply(this, arguments);
		}
	}
}

Object.extend = function(destination, source) {
	for (property in source) destination[property] = source[property];
	return destination;
}

Function.prototype.bind = function(object) {
	var __method = this;
	return function() {
		return __method.apply(object, arguments);
	}
}

Function.prototype.bindAsEventListener = function(object) {
var __method = this;
	return function(event) {
		__method.call(object, event || window.event);
	}
}

function $() {
	if (arguments.length == 1) return get$(arguments[0]);
	var elements = [];
	$c(arguments).each(function(el){
		elements.push(get$(el));
	});
	return elements;

	function get$(el){
		if (typeof el == 'string') el = document.getElementById(el);
		return el;
	}
}

if (!window.Element) var Element = new Object();

Object.extend(Element, {
	remove: function(element) {
		element = $(element);
		element.parentNode.removeChild(element);
	},

	hasClassName: function(element, className) {
		element = $(element);
		if (!element) return;
		var hasClass = false;
		element.className.split(' ').each(function(cn){
			if (cn == className) hasClass = true;
		});
		return hasClass;
	},

	addClassName: function(element, className) {
		element = $(element);
		Element.removeClassName(element, className);
		element.className += ' ' + className;
	},
  
	removeClassName: function(element, className) {
		element = $(element);
		if (!element) return;
		var newClassName = '';
		element.className.split(' ').each(function(cn, i){
			if (cn != className){
				if (i > 0) newClassName += ' ';
				newClassName += cn;
			}
		});
		element.className = newClassName;
	},

	cleanWhitespace: function(element) {
		element = $(element);
		$c(element.childNodes).each(function(node){
			if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node);
		});
	},

	find: function(element, what) {
		element = $(element)[what];
		while (element.nodeType != 1) element = element[what];
		return element;
	}
});

var Position = {
	cumulativeOffset: function(element) {
		var valueT = 0, valueL = 0;
		do {
			valueT += element.offsetTop  || 0;
			valueL += element.offsetLeft || 0;
			element = element.offsetParent;
		} while (element);
		return [valueL, valueT];
	}
};

document.getElementsByClassName = function(className) {
	var children = document.getElementsByTagName('*') || document.all;
	var elements = [];
	$c(children).each(function(child){
		if (Element.hasClassName(child, className)) elements.push(child);
	});  
	return elements;
}

//useful array functions
Array.prototype.iterate = function(func){
	for(var i=0;i<this.length;i++) func(this[i], i);
}
if (!Array.prototype.each) Array.prototype.each = Array.prototype.iterate;

function $c(array){
	var nArray = [];
	for (var i=0;i<array.length;i++) nArray.push(array[i]);
	return nArray;
}

/*
moo.fx, simple effects library built with prototype.js (http://prototype.conio.net).
by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE.
for more info (http://moofx.mad4milk.net).
Sunday, March 05, 2006
v 1.2.3
*/

var fx = new Object();
//base
fx.Base = function(){};
fx.Base.prototype = {
	setOptions: function(options) {
	this.options = {
		duration: 500,
		onComplete: '',
		transition: fx.sinoidal
	}
	Object.extend(this.options, options || {});
	},

	step: function() {
		var time  = (new Date).getTime();
		if (time >= this.options.duration+this.startTime) {
			this.now = this.to;
			clearInterval (this.timer);
			this.timer = null;
			if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10);
		}
		else {
			var Tpos = (time - this.startTime) / (this.options.duration);
			this.now = this.options.transition(Tpos) * (this.to-this.from) + this.from;
		}
		this.increase();
	},

	custom: function(from, to) {
		if (this.timer != null) return;
		this.from = from;
		this.to = to;
		this.startTime = (new Date).getTime();
		this.timer = setInterval (this.step.bind(this), 13);
	},

	hide: function() {
		this.now = 0;
		this.increase();
	},

	clearTimer: function() {
		clearInterval(this.timer);
		this.timer = null;
	}
}

//stretchers
fx.Layout = Class.create();
fx.Layout.prototype = Object.extend(new fx.Base(), {
	initialize: function(el, options) {
		this.el = $(el);
		this.el.style.overflow = "hidden";
		this.iniWidth = this.el.offsetWidth;
		this.iniHeight = this.el.offsetHeight;
		this.setOptions(options);
	}
});

fx.Height = Class.create();
Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), {	
	increase: function() {
		this.el.style.height = this.now + "px";
	},

	toggle: function() {
		if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0);
		else this.custom(0, this.el.scrollHeight);
	}
});

fx.Width = Class.create();
Object.extend(Object.extend(fx.Width.prototype, fx.Layout.prototype), {	
	increase: function() {
		this.el.style.width = this.now + "px";
	},

	toggle: function(){
		if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0);
		else this.custom(0, this.iniWidth);
	}
});

//fader
fx.Opacity = Class.create();
fx.Opacity.prototype = Object.extend(new fx.Base(), {
	initialize: function(el, options) {
		this.el = $(el);
		this.now = 1;
		this.increase();
		this.setOptions(options);
	},

	increase: function() {
		if (this.now == 1 && (/Firefox/.test(navigator.userAgent))) this.now = 0.9999;
		this.setOpacity(this.now);
	},
	
	setOpacity: function(opacity) {
		if (opacity == 0 && this.el.style.visibility != "hidden") this.el.style.visibility = "hidden";
		else if (this.el.style.visibility != "visible") this.el.style.visibility = "visible";
		if (window.ActiveXObject) this.el.style.filter = "alpha(opacity=" + opacity*100 + ")";
		this.el.style.opacity = opacity;
	},

	toggle: function() {
		if (this.now > 0) this.custom(1, 0);
		else this.custom(0, 1);
	}
});

//transitions
fx.sinoidal = function(pos){
	return ((-Math.cos(pos*Math.PI)/2) + 0.5);
	//this transition is from script.aculo.us
}
fx.linear = function(pos){
	return pos;
}
fx.cubic = function(pos){
	return Math.pow(pos, 3);
}
fx.circ = function(pos){
	return Math.sqrt(pos);
}

/*
moo.fx pack, effects extensions for moo.fx.
by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE
for more info visit (http://moofx.mad4milk.net).
Friday, April 14, 2006
v 1.2.4
*/

function testfn()
{
 console.log("testfn"); 
}

//smooth scroll
fx.Scroll = Class.create();
fx.Scroll.prototype = Object.extend(new fx.Base(), {
	initialize: function(options) {
		this.setOptions(options);
	},

	scrollTo: function(el){
		var dest = Position.cumulativeOffset($(el))[1];
		var client = window.innerHeight || document.documentElement.clientHeight;
		var full = document.documentElement.scrollHeight;
		var top = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
		if (dest+client > full) this.custom(top, dest - client + (full-dest));
		else this.custom(top, dest);
	},

	increase: function(){
		window.scrollTo(0, this.now);
	}
});

//text size modify, now works with pixels too.
fx.Text = Class.create();
fx.Text.prototype = Object.extend(new fx.Base(), {
	initialize: function(el, options) {
		this.el = $(el);
		this.setOptions(options);
		if (!this.options.unit) this.options.unit = "em";
	},

	increase: function() {
		this.el.style.fontSize = this.now + this.options.unit;
	}
});

//composition effect: widht/height/opacity
fx.Combo = Class.create();
fx.Combo.prototype = {
	setOptions: function(options) {
		this.options = {
			opacity: true,
			height: true,
			width: false
		}
		Object.extend(this.options, options || {});
	},

	initialize: function(el, options) {
		this.el = $(el);
		this.setOptions(options);
		if (this.options.opacity) {
			this.o = new fx.Opacity(el, options);
			options.onComplete = null;
		}
		if (this.options.height) {
			this.h = new fx.Height(el, options);
			options.onComplete = null;
		}
		if (this.options.width) this.w = new fx.Width(el, options);
	},
	
	toggle: function() { this.checkExec('toggle'); },

	hide: function(){ this.checkExec('hide'); },
	
	clearTimer: function(){ this.checkExec('clearTimer'); },
	
	checkExec: function(func){
		if (this.o) this.o[func]();
		if (this.h) this.h[func]();
		if (this.w) this.w[func]();
	},
	
	//only if width+height
	resizeTo: function(hto, wto) {
		if (this.h && this.w) {
			this.h.custom(this.el.offsetHeight, this.el.offsetHeight + hto);
			this.w.custom(this.el.offsetWidth, this.el.offsetWidth + wto);
		}
	},

	customSize: function(hto, wto) {
		if (this.h && this.w) {
			this.h.custom(this.el.offsetHeight, hto);
			this.w.custom(this.el.offsetWidth, wto);
		}
	}
}

fx.Accordion = Class.create();
fx.Accordion.prototype = {
	setOptions: function(options) {
		this.options = {
			delay: 100,
			opacity: false
		}
		Object.extend(this.options, options || {});
	},

	initialize: function(togglers, elements, options) {
		this.elements = elements;
		this.setOptions(options);
		var options = options || '';
		this.fxa = [];
		if (options && options.onComplete) options.onFinish = options.onComplete;
		elements.each(function(el, i){
			options.onComplete = function(){
				if (el.offsetHeight > 0) el.style.height = '1%';
				if (options.onFinish) options.onFinish(el);
			}
			this.fxa[i] = new fx.Combo(el, options);
			this.fxa[i].hide();
		}.bind(this));

		togglers.each(function(tog, i){
			if (typeof tog.onclick == 'function') var exClick = tog.onclick;
			tog.onclick = function(){
				if (exClick) exClick();
				this.showThisHideOpen(elements[i]);
	      accordion_open_start(tog);
			}.bind(this);
		}.bind(this));
	},

	showThisHideOpen: function(toShow){
		this.elements.each(function(el, j){
			if (el.offsetHeight > 0 && el != toShow) this.clearAndToggle(el, j);
			if (el == toShow && toShow.offsetHeight == 0) 
			{
			  setTimeout(
			    function() {
			      this.clearAndToggle(toShow, j);
			    }.bind(this), 
			    this.options.delay);
			}
		}.bind(this));
	},

	clearAndToggle: function(el, i){
		this.fxa[i].clearTimer();
		this.fxa[i].toggle();
	}
}

var Remember = new Object();
Remember = function(){};
Remember.prototype = {
	initialize: function(el, options){
		this.el = $(el);
		this.days = 365;
		this.options = options;
		this.effect();
		var cookie = this.readCookie();
		if (cookie) {
			this.fx.now = cookie;
			this.fx.increase();
		}
	},

	//cookie functions based on code by Peter-Paul Koch
	setCookie: function(value) {
		var date = new Date();
		date.setTime(date.getTime()+(this.days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
		document.cookie = this.el+this.el.id+this.prefix+"="+value+expires+"; path=/";
	},

	readCookie: function() {
		var nameEQ = this.el+this.el.id+this.prefix + "=";
		var ca = document.cookie.split(';');
		for(var i=0;c=ca[i];i++) {
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return false;
	},

	custom: function(from, to){
		if (this.fx.now != to) {
			this.setCookie(to);
			this.fx.custom(from, to);
		}
	}
}

fx.RememberHeight = Class.create();
fx.RememberHeight.prototype = Object.extend(new Remember(), {
	effect: function(){
		this.fx = new fx.Height(this.el, this.options);
		this.prefix = 'height';
	},
	
	toggle: function(){
		if (this.el.offsetHeight == 0) this.setCookie(this.el.scrollHeight);
		else this.setCookie(0);
		this.fx.toggle();
	},
	
	resize: function(to){
		this.setCookie(this.el.offsetHeight+to);
		this.fx.custom(this.el.offsetHeight,this.el.offsetHeight+to);
	},

	hide: function(){
		if (!this.readCookie()) {
			this.fx.hide();
		}
	}
});

fx.RememberText = Class.create();
fx.RememberText.prototype = Object.extend(new Remember(), {
	effect: function(){
		this.fx = new fx.Text(this.el, this.options);
		this.prefix = 'text';
	}
});

//useful for-replacement
Array.prototype.iterate = function(func){
	for(var i=0;i<this.length;i++) func(this[i], i);
}
if (!Array.prototype.each) Array.prototype.each = Array.prototype.iterate;

//Easing Equations (c) 2003 Robert Penner, all rights reserved.
//This work is subject to the terms in http://www.robertpenner.com/easing_terms_of_use.html.

//expo
fx.expoIn = function(pos){
	return Math.pow(2, 10 * (pos - 1));
}
fx.expoOut = function(pos){
	return (-Math.pow(2, -10 * pos) + 1);
}

//quad
fx.quadIn = function(pos){
	return Math.pow(pos, 2);
}
fx.quadOut = function(pos){
	return -(pos)*(pos-2);
}

//circ
fx.circOut = function(pos){
	return Math.sqrt(1 - Math.pow(pos-1,2));
}
fx.circIn = function(pos){
	return -(Math.sqrt(1 - Math.pow(pos, 2)) - 1);
}

//back
fx.backIn = function(pos){
	return (pos)*pos*((2.7)*pos - 1.7);
}
fx.backOut = function(pos){
	return ((pos-1)*(pos-1)*((2.7)*(pos-1) + 1.7) + 1);
}

//sine
fx.sineOut = function(pos){
	return Math.sin(pos * (Math.PI/2));
}
fx.sineIn = function(pos){
	return -Math.cos(pos * (Math.PI/2)) + 1;
}
fx.sineInOut = function(pos){
	return -(Math.cos(Math.PI*pos) - 1)/2;
}

//MooTools, My Object Oriented Javascript Tools. Copyright (c) 2006 Valerio Proietti, <http://mad4milk.net>, MIT Style License.
var Class = function(properties){
	var klass = function(){
		if (this.initialize && arguments[0] != 'noinit') return this.initialize.apply(this, arguments);
		else return this;
	};
	for (var property in this) klass[property] = this[property];
	klass.prototype = properties;
	return klass;
};

Class.empty = function(){};

Class.prototype = {

	extend: function(properties){
		var pr0t0typ3 = new this('noinit');

		var parentize = function(previous, current){
			if (!previous.apply || !current.apply) return false;
			return function(){
				this.parent = previous;
				return current.apply(this, arguments);
			};
		};

		for (var property in properties){
			var previous = pr0t0typ3[property];
			var current = properties[property];
			if (previous && previous != current) current = parentize(previous, current) || current;
			pr0t0typ3[property] = current;
		}
		return new Class(pr0t0typ3);
	},

	implement: function(properties){
		for (var property in properties) this.prototype[property] = properties[property];
	}

};

Object.extend = function(){
	var args = arguments;
	args = (args[1]) ? [args[0], args[1]] : [this, args[0]];
	for (var property in args[1]) args[0][property] = args[1][property];
	return args[0];
};

Object.Native = function(){
	for (var i = 0; i < arguments.length; i++) arguments[i].extend = Class.prototype.implement;
};

new Object.Native(Function, Array, String, Number, Class);

if (typeof HTMLElement == 'undefined'){
	var HTMLElement = Class.empty;
	HTMLElement.prototype = {};
} else {
	HTMLElement.prototype.htmlElement = true;
}

window.extend = document.extend = Object.extend;
var Window = window;

function $defined(obj){
	return (obj != undefined);	
}

function $type(obj){
	if (obj === null || obj === undefined) return false;
	var type = typeof obj;
	if (type == 'object'){
		if (obj.htmlElement) return 'element';
		if (obj.push) return 'array';
		if (obj.nodeName){
			switch (obj.nodeType){
				case 1: return 'element';
				case 3: return obj.nodeValue.test(/\S/) ? 'textnode' : 'whitespace';
			}
		}
	}
	return type;
};

function $chk(obj){
	return !!(obj || obj === 0);
};

function $pick(obj, picked){
	return ($type(obj)) ? obj : picked;
};

function $random(min, max){
	return Math.floor(Math.random() * (max - min + 1) + min);
};

function $clear(timer){
	clearTimeout(timer);
	clearInterval(timer);
	return null;
};

if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true;
else if (document.childNodes && !document.all && !navigator.taintEnabled) window.khtml = true;
else if (document.getBoxObjectFor != null) window.gecko = true;

if (window.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch (e){};

Array.prototype.forEach = Array.prototype.forEach || function(fn, bind){
	for (var i = 0; i < this.length; i++) fn.call(bind, this[i], i, this);
};

Array.prototype.filter = Array.prototype.filter || function(fn, bind){
	var results = [];
	for (var i = 0; i < this.length; i++){
		if (fn.call(bind, this[i], i, this)) results.push(this[i]);
	}
	return results;
};

Array.prototype.map = Array.prototype.map || function(fn, bind){
	var results = [];
	for (var i = 0; i < this.length; i++) results[i] = fn.call(bind, this[i], i, this);
	return results;
};

Array.prototype.every = Array.prototype.every || function(fn, bind){
	for (var i = 0; i < this.length; i++){
		if (!fn.call(bind, this[i], i, this)) return false;
	}
	return true;
};

Array.prototype.some = Array.prototype.some || function(fn, bind){
	for (var i = 0; i < this.length; i++){
		if (fn.call(bind, this[i], i, this)) return true;
	}
	return false;
};

Array.prototype.indexOf = Array.prototype.indexOf || function(item, from){
	from = from || 0;
	if (from < 0) from = Math.max(0, this.length + from);
	while (from < this.length){
		if(this[from] === item) return from;
		from++;
	}
	return -1;

};

Array.extend({

	each: Array.prototype.forEach,

	copy: function(start, length){
		start = start || 0;
		if (start < 0) start = this.length + start;
		length = length || (this.length - start);
		var newArray = [];
		for (var i = 0; i < length; i++) newArray[i] = this[start++];
		return newArray;
	},

	remove: function(item){
		var i = 0;
		while (i < this.length){
			if (this[i] === item) this.splice(i, 1);
			else i++;
		}
		return this;
	},
	test: function(item, from){
		return this.indexOf(item, from) != -1;
	},

	extend: function(newArray){
		for (var i = 0; i < newArray.length; i++) this.push(newArray[i]);
		return this;
	},

	associate: function(keys){
		var obj = {}, length = Math.min(this.length, keys.length);
		for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
		return obj;
	}

});

function $A(array, start, length){
	return Array.prototype.copy.call(array, start, length);
};

function $each(iterable, fn, bind){
	return Array.prototype.forEach.call(iterable, fn, bind);
};

String.extend({

	test: function(regex, params){
		return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);
	},

	toInt: function(){
		return parseInt(this);
	},

	toFloat: function(){
		return parseFloat(this);
	},

	camelCase: function(){
		return this.replace(/-\D/g, function(match){
			return match.charAt(1).toUpperCase();
		});
	},

	hyphenate: function(){
		return this.replace(/\w[A-Z]/g, function(match){
			return (match.charAt(0)+'-'+match.charAt(1).toLowerCase());
		});
	},

	capitalize: function(){
		return this.toLowerCase().replace(/\b[a-z]/g, function(match){
			return match.toUpperCase();
		});
	},

	trim: function(){
		return this.replace(/^\s+|\s+$/g, '');
	},

	clean: function(){
		return this.replace(/\s{2,}/g, ' ').trim();
	},

	rgbToHex: function(array){
		var rgb = this.match(/\d{1,3}/g);
		return (rgb) ? rgb.rgbToHex(array) : false;
	},

	hexToRgb: function(array){
		var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
		return (hex) ? hex.slice(1).hexToRgb(array) : false;
	}

});

Array.extend({

	rgbToHex: function(array){
		if (this.length < 3) return false;
		if (this[3] && (this[3] == 0) && !array) return 'transparent';
		var hex = [];
		for (var i = 0; i < 3; i++){
			var bit = (this[i]-0).toString(16);
			hex.push((bit.length == 1) ? '0'+bit : bit);
		}
		return array ? hex : '#'+hex.join('');
	},

	hexToRgb: function(array){
		if (this.length != 3) return false;
		var rgb = [];
		for (var i = 0; i < 3; i++){
			rgb.push(parseInt((this[i].length == 1) ? this[i]+this[i] : this[i], 16));
		}
		return array ? rgb : 'rgb('+rgb.join(',')+')';
	}

});

Number.extend({

	toInt: function(){
		return parseInt(this);
	},

	toFloat: function(){
		return parseFloat(this);
	}

});

Function.extend({

	create: function(options){
		var fn = this;
		options = Object.extend({
			'bind': fn, 
			'event': false, 
			'arguments': null, 
			'delay': false, 
			'periodical': false, 
			'attempt': false
		}, options || {});
		if ($chk(options.arguments) && $type(options.arguments) != 'array') options.arguments = [options.arguments];
		return function(event){
			var args;
			if (options.event){
				event = event || window.event;
				args = [(options.event === true) ? event : new options.event(event)];
				if (options.arguments) args = args.concat(options.arguments);
			}
			else args = options.arguments || arguments;
			var returns = function(){
				return fn.apply(options.bind, args);
			};
			if (options.delay) return setTimeout(returns, options.delay);
			if (options.periodical) return setInterval(returns, options.periodical);
			if (options.attempt){
				try {
					return returns();
				} catch(err){
					return err;
				}
			}
			return returns();
		};
	},

	pass: function(args, bind){
		return this.create({'arguments': args, 'bind': bind});
	},

	attempt: function(args, bind){
		return this.create({'arguments': args, 'bind': bind, 'attempt': true})();
	},

	bind: function(bind, args){
		return this.create({'bind': bind, 'arguments': args});
	},

	bindAsEventListener: function(bind, args){
		return this.create({'bind': bind, 'event': true, 'arguments': args});
	},

	delay: function(ms, bind, args){
		return this.create({'delay': ms, 'bind': bind, 'arguments': args})();
	},

	periodical: function(ms, bind, args){
		return this.create({'periodical': ms, 'bind': bind, 'arguments': args})();
	}

});

var Element = new Class({

	initialize: function(el){
		if ($type(el) == 'string') el = document.createElement(el);
		return $(el);
	}

});

function $(el){
	if (!el) return false;
	if (el._element_extended_ || [window, document].test(el)) return el;
	if ($type(el) == 'string') el = document.getElementById(el);
	if ($type(el) != 'element') return false;
	if (['object', 'embed'].test(el.tagName.toLowerCase()) || el.extend) return el;
	el._element_extended_ = true;
	Garbage.collect(el);
	el.extend = Object.extend;
	if (!(el.htmlElement)) el.extend(Element.prototype);
	return el;
};

var Elements = new Class({});

new Object.Native(Elements);

document.getElementsBySelector = document.getElementsByTagName;

function $$(){
	if (!arguments) return false;
	if (arguments.length == 1){
		if (!arguments[0]) return false;
		if (arguments[0]._elements_extended_) return arguments[0];
	}
	var elements = [];
	$each(arguments, function(selector){
		switch ($type(selector)){
			case 'element': elements.push($(selector)); break;
			case 'string': selector = document.getElementsBySelector(selector);
			default:
			if (selector.length){
				$each(selector, function(el){
					if ($(el)) elements.push(el);
				});
			}
		}
	});
	elements._elements_extended_ = true;
	return Object.extend(elements, new Elements);
};

Elements.Multi = function(property){
	return function(){
		var args = arguments;
		var items = [];
		var elements = true;
		$each(this, function(el){
			var returns = el[property].apply(el, args);
			if ($type(returns) != 'element') elements = false;
			items.push(returns);
		});
		if (elements) items = $$(items);
		return items;
	};
};

Element.extend = function(properties){
	for (var property in properties){
		HTMLElement.prototype[property] = properties[property];
		Element.prototype[property] = properties[property];
		Elements.prototype[property] = Elements.Multi(property);
	}
};

Element.extend({

	inject: function(el, where){
		el = $(el) || new Element(el);
		switch (where){
			case "before": $(el.parentNode).insertBefore(this, el); break;
			case "after":
				if (!el.getNext()) $(el.parentNode).appendChild(this);
				else $(el.parentNode).insertBefore(this, el.getNext());
				break;
			case 'top':
				var first = el.firstChild;
				if (first){
					el.insertBefore(this, first);
					break;
				}
			case "inside": el.appendChild(this);
		}
		return this;
	},

	injectBefore: function(el){
		return this.inject(el, 'before');
	},

	injectAfter: function(el){
		return this.inject(el, 'after');
	},

	injectTop: function(el){
		return this.inject(el, 'top');
	},

	injectInside: function(el){
		return this.inject(el, 'inside');
	},

	adopt: function(el){
		this.appendChild($(el) || new Element(el));
		return this;
	},

	remove: function(){
		this.parentNode.removeChild(this);
		return this;
	},

	clone: function(contents){
		var el = this.cloneNode(contents !== false);
		return $(el);
	},

	replaceWith: function(el){
		el = $(el) || new Element(el);
		this.parentNode.replaceChild(el, this);
		return el;
	},

	appendText: function(text){
		if (window.ie){
			switch(this.getTag()){
				case 'style': this.styleSheet.cssText = text; return this;
				case 'script': this.setProperty('text', text); return this;
			}
		}
		this.appendChild(document.createTextNode(text));
		return this;
	},

	hasClass: function(className){
		return this.className.test('(?:^|\\s)'+className+'(?:\\s|$)');
	},

	addClass: function(className){
		if (!this.hasClass(className)) this.className = (this.className+' '+className).clean();
		return this;
	},

	removeClass: function(className){
		this.className = this.className.replace(new RegExp('(^|\\s)'+className+'(?:\\s|$)'), '$1').clean();
		return this;
	},

	toggleClass: function(className){
		return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
	},

	setStyle: function(property, value){
		if (property == 'opacity') this.setOpacity(parseFloat(value));
		else this.style[property.camelCase()] = (value.push) ? 'rgb('+value.join(',')+')' : value;
		return this;
	},

	setStyles: function(source){
		switch ($type(source)){
			case 'object':
				for (var property in source) this.setStyle(property, source[property]);
				break;
			case 'string':
				this.style.cssText = source;
		}
		return this;
	},

	setOpacity: function(opacity){
		if (opacity == 0){
			if(this.style.visibility != "hidden") this.style.visibility = "hidden";
		} else {
			if(this.style.visibility != "visible") this.style.visibility = "visible";
		}
		if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
		if (window.ie) this.style.filter = "alpha(opacity=" + opacity*100 + ")";
		this.style.opacity = this.opacity = opacity;
		return this;
	},

	getStyle: function(property){
		property = property.camelCase();
		var style = this.style[property] || false;
		if (!$chk(style)){
			if (property == 'opacity') return $chk(this.opacity) ? this.opacity : 1;
			if (['margin', 'padding'].test(property)){
				return [this.getStyle(property+'-top') || 0, this.getStyle(property+'-right') || 0,
						this.getStyle(property+'-bottom') || 0, this.getStyle(property+'-left') || 0].join(' ');
			}
			if (document.defaultView) style = document.defaultView.getComputedStyle(this, null).getPropertyValue(property.hyphenate());
			else if (this.currentStyle) style = this.currentStyle[property];
		}
		if (style == 'auto' && ['height', 'width'].test(property)) return this['offset'+property.capitalize()]+'px';
		return (style && property.test(/color/i) && style.test(/rgb/)) ? style.rgbToHex() : style;
	},

	addEvent: function(type, fn){
		this.events = this.events || {};
		this.events[type] = this.events[type] || {'keys': [], 'values': []};
		if (!this.events[type].keys.test(fn)){
			this.events[type].keys.push(fn);
			if (this.addEventListener){
				this.addEventListener((type == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : type, fn, false);
			} else {
				fn = fn.bind(this);
				this.attachEvent('on'+type, fn);
				this.events[type].values.push(fn);
			}
		}
		return this;
	},

	addEvents: function(source){
		if (source){
			for (var type in source) this.addEvent(type, source[type]);
		}
		return this;
	},

	removeEvent: function(type, fn){
		if (this.events && this.events[type]){
			var pos = this.events[type].keys.indexOf(fn);
			if (pos == -1) return this;
			var key = this.events[type].keys.splice(pos,1)[0];
			if (this.removeEventListener){
				this.removeEventListener((type == 'mousewheel' && window.gecko) ? 'DOMMouseScroll' : type, key, false);
			} else {
				this.detachEvent('on'+type, this.events[type].values.splice(pos,1)[0]);
			}
		}
		return this;
	},

	removeEvents: function(type){
		if (this.events){
			if (type){
				if (this.events[type]){
					this.events[type].keys.each(function(fn){
						this.removeEvent(type, fn);
					}, this);
					this.events[type] = null;
				}
			} else {
				for (var evType in this.events) this.removeEvents(evType);
				this.events = null;
			}
		}
		return this;
	},

	fireEvent: function(type, args){
		if (this.events && this.events[type]){
			this.events[type].keys.each(function(fn){
				fn.bind(this, args)();
			}, this);
		}
	},

	getBrother: function(what){
		var el = this[what+'Sibling'];
		while ($type(el) == 'whitespace') el = el[what+'Sibling'];
		return $(el);
	},

	getPrevious: function(){
		return this.getBrother('previous');
	},

	getNext: function(){
		return this.getBrother('next');
	},

	getFirst: function(){
		var el = this.firstChild;
		while ($type(el) == 'whitespace') el = el.nextSibling;
		return $(el);
	},

	getLast: function(){
		var el = this.lastChild;
		while ($type(el) == 'whitespace') el = el.previousSibling;
		return $(el);
	},

	getParent: function(){
		return $(this.parentNode);
	},

	getChildren: function(){
		return $$(this.childNodes);
	},

	setProperty: function(property, value){
		switch (property){
			case 'class': this.className = value; break;
			case 'style': this.setStyles(value); break;
			case 'name': if (window.ie6){
				var el = $(document.createElement('<'+this.getTag()+' name="'+value+'" />'));
				$each(this.attributes, function(attribute){
					if (attribute.name != 'name') el.setProperty(attribute.name, attribute.value);
				});
				if (this.parentNode) this.replaceWith(el);
				return el;
			}
			default: this.setAttribute(property, value);
		}
		return this;
	},

	setProperties: function(source){
		for (var property in source) this.setProperty(property, source[property]);
		return this;
	},

	setHTML: function(){
		this.innerHTML = $A(arguments).join('');
		return this;
	},

	getProperty: function(property){
		return (property == 'class') ? this.className : this.getAttribute(property);
	},

	getTag: function(){
		return this.tagName.toLowerCase();
	},

	scrollTo: function(x, y){
		this.scrollLeft = x;
		this.scrollTop = y;
	},

	getValue: function(){
		switch (this.getTag()){
			case 'select':
				if (this.selectedIndex != -1){
					var opt = this.options[this.selectedIndex];
					return opt.value || opt.text;
				}
				break;
			case 'input': if (!(this.checked && ['checkbox', 'radio'].test(this.type)) && !['hidden', 'text', 'password'].test(this.type)) break;
			case 'textarea': return this.value;
		}
		return false;
	},

	getSize: function(){
		return {
			'scroll': {'x': this.scrollLeft, 'y': this.scrollTop},
			'size': {'x': this.offsetWidth, 'y': this.offsetHeight},
			'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight}
		};
	},

	getPosition: function(overflown){
		overflown = overflown || [];
		var el = this, left = 0, top = 0;
		do {
			left += el.offsetLeft || 0;
			top += el.offsetTop || 0;
			el = el.offsetParent;
		} while (el);
		overflown.each(function(element){
			left -= element.scrollLeft || 0;
			top -= element.scrollTop || 0;
		});
		return {'x': left, 'y': top};
	},

	getTop: function(){
		return this.getPosition().y;
	},

	getLeft: function(){
		return this.getPosition().x;
	},

	getCoordinates: function(overflown){
		var position = this.getPosition(overflown);
		var obj = {
			'width': this.offsetWidth,
			'height': this.offsetHeight,
			'left': position.x,
			'top': position.y
		};
		obj.right = obj.left + obj.width;
		obj.bottom = obj.top + obj.height;
		return obj;
	}

});

window.addEvent = document.addEvent = Element.prototype.addEvent;
window.removeEvent = document.removeEvent = Element.prototype.removeEvent;
window.removeEvents = document.removeEvents = Element.prototype.removeEvents;

var Garbage = {

	elements: [],

	collect: function(element){
		Garbage.elements.push(element);
	},

	trash: function(){
		Garbage.collect(window);
		Garbage.collect(document);
		Garbage.elements.each(function(el){
			el.removeEvents();
			for (var p in Element.prototype) el[p] = null;
			el.extend = null;
		});
	}

};

window.addEvent('unload', Garbage.trash);

var Event = new Class({

	initialize: function(event){
		this.event = event || window.event;
		this.type = this.event.type;
		this.target = this.event.target || this.event.srcElement;
		if (this.target.nodeType == 3) this.target = this.target.parentNode;
		this.shift = this.event.shiftKey;
		this.control = this.event.ctrlKey;
		this.alt = this.event.altKey;
		this.meta = this.event.metaKey;
		if (['DOMMouseScroll', 'mousewheel'].test(this.type)){
			this.wheel = this.event.wheelDelta ? (this.event.wheelDelta / (window.opera ? -120 : 120)) : -(this.event.detail || 0) / 3;
		} else if (this.type.test(/key/)){
			this.code = this.event.which || this.event.keyCode;
			for (var name in Event.keys){
				if (Event.keys[name] == this.code){
					this.key = name;
					break;
				}
			}
			this.key = this.key || String.fromCharCode(this.code).toLowerCase();

		} else if (this.type.test(/mouse/) || (this.type == 'click')){
			this.page = {
				'x': this.event.pageX || this.event.clientX + document.documentElement.scrollLeft,
				'y': this.event.pageY || this.event.clientY + document.documentElement.scrollTop
			};
			this.client = {
				'x': this.event.pageX ? this.event.pageX - window.pageXOffset : this.event.clientX,
				'y': this.event.pageY ? this.event.pageY - window.pageYOffset : this.event.clientY
			};
			this.rightClick = (this.event.which == 3) || (this.event.button == 2);
			switch (this.type){
				case 'mouseover': this.relatedTarget = this.event.relatedTarget || this.event.fromElement; break;
				case 'mouseout': this.relatedTarget = this.event.relatedTarget || this.event.toElement;
			}
		}
	},

	stop: function() {
		this.stopPropagation();
		this.preventDefault();
		return this;
	},

	stopPropagation: function(){
		if (this.event.stopPropagation) this.event.stopPropagation();
		else this.event.cancelBubble = true;
		return this;
    },

	preventDefault: function(){
		if (this.event.preventDefault) this.event.preventDefault();
		else this.event.returnValue = false;
		return this;
	}

});

Event.keys = {
	'enter': 13,
	'up': 38,
	'down': 40,
	'left': 37,
	'right': 39,
	'esc': 27,
	'space': 32,
	'backspace': 8,
	'delete': 46
};

Function.extend({

	bindWithEvent: function(bind, args){
		return this.create({'bind': bind, 'arguments': args, 'event': Event});
	}

});

var Chain = new Class({

	chain: function(fn){
		this.chains = this.chains || [];
		this.chains.push(fn);
		return this;
	},

	callChain: function(){
		if (this.chains && this.chains.length) this.chains.shift().delay(10, this);
	},

	clearChain: function(){
		this.chains = [];
	}

});

var Events = new Class({

	addEvent: function(type, fn){
		if (fn != Class.empty){
			this.events = this.events || {};
			this.events[type] = this.events[type] || [];
			if (!this.events[type].test(fn)) this.events[type].push(fn);
		}
		return this;
	},

	fireEvent: function(type, args, delay){
		if (this.events && this.events[type]){
			this.events[type].each(function(fn){
				fn.create({'bind': this, 'delay': delay, 'arguments': args})();
			}, this);
		}
		return this;
	},

	removeEvent: function(type, fn){
		if (this.events && this.events[type]) this.events[type].remove(fn);
		return this;
	}

});

var Options = new Class({

	setOptions: function(defaults, options){
		this.options = Object.extend(defaults, options);
		if (this.addEvent){
			for (var option in this.options){
				if (($type(this.options[option]) == 'function') && option.test(/^on[A-Z]/)) this.addEvent(option, this.options[option]);
			}
		}
		return this;
	}

});

var Group = new Class({

	initialize: function(){
		this.instances = $A(arguments);
		this.events = {};
		this.checker = {};
	},

	addEvent: function(type, fn){
		this.checker[type] = this.checker[type] || {};
		this.events[type] = this.events[type] || [];
		if (this.events[type].test(fn)) return false;
		else this.events[type].push(fn);
		this.instances.each(function(instance, i){
			instance.addEvent(type, this.check.bind(this, [type, instance, i]));
		}, this);
		return this;
	},

	check: function(type, instance, i){
		this.checker[type][i] = true;
		var every = this.instances.every(function(current, j){
			return this.checker[type][j] || false;
		}, this);
		if (!every) return;
		this.instances.each(function(current, j){
			this.checker[type][j] = false;
		}, this);
		this.events[type].each(function(event){
			event.call(this, this.instances, instance);
		}, this);
	}

});

function $E(selector, filter){
	return ($(filter) || document).getElement(selector);
};

function $ES(selector, filter){
	return ($(filter) || document).getElementsBySelector(selector);
};

Element.extend({

	getElements: function(selector){
		var elements = [];
		selector.clean().split(' ').each(function(sel, i){
			var param = sel.match(/^(\w*|\*)(?:#([\w-]+)|\.([\w-]+))?(?:\[(\w+)(?:([*^$]?=)["']?([^"'\]]*)["']?)?])?$/);
			if (!param) return;
			Filters.selector = param;
			param[1] = param[1] || '*';
			if (i == 0){
				if (param[2]){
					var el = this.getElementById(param[2]);
					if (!el || ((param[1] != '*') && (Element.prototype.getTag.call(el) != param[1]))) return;
					elements = [el];
				} else {
					elements = $A(this.getElementsByTagName(param[1]));
				}
			} else {
				elements = Elements.prototype.getElementsByTagName.call(elements, param[1], true);
				if (param[2]) elements = elements.filter(Filters.id);
			}
			if (param[3]) elements = elements.filter(Filters.className);
			if (param[4]) elements = elements.filter(Filters.attribute);
		}, this);
		return $$(elements);
	},

	getElementById: function(id){
		var el = document.getElementById(id);
		if (!el) return false;
		for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
			if (!parent) return false;
		}
		return el;
	},

	getElement: function(selector){
		return this.getElementsBySelector(selector)[0];
	},

	getElementsBySelector: function(selector){
		var els = [];
		selector.split(',').each(function(sel){
			els.extend(this.getElements(sel));
		}, this);
		return $$(els);
	}

});

document.extend({

	getElementsByClassName: function(className){
		return document.getElements('.'+className);
	},
	getElement: Element.prototype.getElement,
	getElements: Element.prototype.getElements,
	getElementsBySelector: Element.prototype.getElementsBySelector

});

var Filters = {

	selector: [],

	id: function(el){
		return (el.id == Filters.selector[2]);
	},

	className: function(el){
		return (Element.prototype.hasClass.call(el, Filters.selector[3]));
	},

	attribute: function(el){
		var current = el.getAttribute(Filters.selector[4]);
		if (!current) return false;
		var operator = Filters.selector[5];
		if (!operator) return true;
		var value = Filters.selector[6];
		switch (operator){
			case '*=': return (current.test(value));
			case '=': return (current == value);
			case '^=': return (current.test('^'+value));
			case '$=': return (current.test(value+'$'));
		}
		return false;
	}

};

Elements.extend({

	getElementsByTagName: function(tagName){
		var found = [];
		this.each(function(el){
			found.extend(el.getElementsByTagName(tagName));
		});
		return found;
	}

});

var Hash = new Class({

	length: 0,

	obj: {},

	initialize: function(obj){
		this.extend(obj);
	},

	get: function(key){
		return this.obj[key];
	},

	hasKey: function(key){
		return this.obj[key] !== undefined;
	},

	set: function(key, value){
		if (value === undefined) return false;
		if (this.obj[key] === undefined) this.length++;
		this.obj[key] = value;
		return this;
	},

	remove: function(key){
		if (this.obj[key] === undefined) return this;
		var obj = {};
		this.length--;
		for (var property in this.obj){
			if (property != key) obj[property] = this.obj[property];
		}
		this.obj = obj;
		return this;
	},

	each: function(fn, bind){
		for (var property in this.obj) fn.call(bind || this, property, this.obj[property]);
	},

	extend: function(obj){
		for (var property in obj){
			if (this.obj[property] === undefined) this.length++;
			this.obj[property] = obj[property];
		}
		return this;
	},

	empty: function(){
		return (this.length == 0);
	},

	keys: function(){
		var keys = [];
		for (var property in this.obj) keys.push(property);
		return keys;
	},

	values: function(){
		var values = [];
		for (var property in this.obj) values.push(this.obj[property]);
		return values;
	}

});

function $H(obj){
	return new Hash(obj);
};

var Color = new Class({

	initialize: function(color, type){
		if (color.isColor) return color;
		color.isColor = true;
		type = type || (color.push ? 'rgb' : 'hex');
		var rgb, hsb;
		switch(type){
			case 'rgb':
				rgb = color;
				hsb = rgb.rgbToHsb();
				break;
			case 'hsb':
				rgb = color.hsbToRgb();
				hsb = color;
				break;
			default:
				rgb = color.hexToRgb(true);
				hsb = rgb.rgbToHsb();
		}
		rgb.hsb = hsb;
		return Object.extend(rgb, Color.prototype);
	},

	mix: function(){
		var colors = $A(arguments);
		var alpha = ($type(colors[colors.length-1]) == 'number') ? colors.pop() : 50;
		var rgb = this.copy();
		colors.each(function(color){
			color = new Color(color);
			for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));
		});
		return new Color(rgb, 'rgb');
	},

	invert: function(){
		return new Color(this.map(function(value){
			return 255 - value;
		}));
	},

	setHue: function(value){
		return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
	},

	setSaturation: function(percent){
		return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
	},

	setBrightness: function(percent){
		return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
	}

});

function $RGB(r, g, b){
	return new Color([r, g, b], 'rgb');
};

function $HSB(h, s, b){
	return new Color([h, s, b], 'hsb');
};

Array.extend({

	rgbToHsb: function(){
		var red = this[0], green = this[1], blue = this[2];
		var hue, saturation, brightness;
		var max = Math.max(red, green, blue), min = Math.min(red, green, blue);
		var delta = max - min;
		brightness = max / 255;
		saturation = (max != 0) ? delta / max : 0;
		if (saturation == 0){
			hue = 0;
		} else {
			var rr = (max - red) / delta;
			var gr = (max - green) / delta;
			var br = (max - blue) / delta;
			if (red == max) hue = br - gr;
			else if (green == max) hue = 2 + rr - br;
			else hue = 4 + gr - rr;
			hue /= 6;
			if (hue < 0) hue++;
		}
		return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)];
	},

	hsbToRgb: function(){
		var br = Math.round(this[2] / 100 * 255);
		if (this[1] == 0){
			return [br, br, br];
		} else {
			var hue = this[0] % 360;
			var f = hue % 60;
			var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255);
			var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255);
			var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255);
			switch (Math.floor(hue / 60)){
				case 0: return [br, t, p];
				case 1: return [q, br, p];
				case 2: return [p, br, t];
				case 3: return [p, q, br];
				case 4: return [t, p, br];
				case 5: return [br, p, q];
			}
		}
		return false;
	}

});

window.extend({

	addEvent: function(type, fn){
		if (type == 'domready'){
			if (this.loaded) fn();
			else if (!this.events || !this.events.domready){
				var domReady = function(){
					if (this.loaded) return;
					this.loaded = true;
					if (this.timer) this.timer = $clear(this.timer);
					Element.prototype.fireEvent.call(this, 'domready');
					this.events.domready = null;
				}.bind(this);
				if (document.readyState && this.khtml){
					this.timer = function(){
						if (['loaded','complete'].test(document.readyState)) domReady();
					}.periodical(50);
				}
				else if (document.readyState && this.ie){
					document.write("<script id=ie_ready defer src=javascript:void(0)><\/script>");
					$('ie_ready').onreadystatechange = function(){
						if (this.readyState == 'complete') domReady();
					};
				} else {
					this.addEvent("load", domReady);
					document.addEvent("DOMContentLoaded", domReady);
				}
			}
		}
		Element.prototype.addEvent.call(this, type, fn);
		return this;
	},

	onDomReady: function(init){
		return this.addEvent('domready', init);
	}

});

window.extend({

	getWidth: function(){
		if (this.khtml) return this.innerWidth;
		if (this.opera) return document.body.clientWidth;
		return document.documentElement.clientWidth;
	},

	getHeight: function(){
		if (this.khtml) return this.innerHeight;
		if (this.opera) return document.body.clientHeight;
		return document.documentElement.clientHeight;
	},

	getScrollWidth: function(){
		if (this.ie) return Math.max(document.documentElement.offsetWidth, document.documentElement.scrollWidth);
		if (this.khtml) return document.body.scrollWidth;
		return document.documentElement.scrollWidth;
	},

	getScrollHeight: function(){
		if (this.ie) return Math.max(document.documentElement.offsetHeight, document.documentElement.scrollHeight);
		if (this.khtml) return document.body.scrollHeight;
		return document.documentElement.scrollHeight;
	},

	getScrollLeft: function(){
		return this.pageXOffset || document.documentElement.scrollLeft;
	},

	getScrollTop: function(){
		return this.pageYOffset || document.documentElement.scrollTop;
	},

	getSize: function(){
		return {
			'size': {'x': this.getWidth(), 'y': this.getHeight()},
			'scrollSize': {'x': this.getScrollWidth(), 'y': this.getScrollHeight()},
			'scroll': {'x': this.getScrollLeft(), 'y': this.getScrollTop()}
		};
	},
	getPosition: function(){return {'x': 0, 'y': 0}},
	
	getHash: function() {
		return window.location.hash;	
	}

	

});

var Fx = {};

Fx.Base = new Class({

	getOptions: function(){
		return {
			onStart: Class.empty,
			onComplete: Class.empty,
			onCancel: Class.empty,
			transition: Fx.Transitions.sineInOut,
			duration: 500,
			unit: 'px',
			wait: true,
			fps: 50
		};
	},

	initialize: function(options){
		this.element = this.element || null;
		this.setOptions(this.getOptions(), options);
		if (this.options.initialize) this.options.initialize.call(this);
	},

	step: function(){
		var time = new Date().getTime();
		if (time < this.time + this.options.duration){
			this.cTime = time - this.time;
			this.setNow();
			this.increase();
		} else {
			this.stop(true);
			this.now = this.to;
			this.increase();
			this.fireEvent('onComplete', this.element, 10);
			this.callChain();
		}
	},

	set: function(to){
		this.now = to;
		this.increase();
		return this;
	},

	setNow: function(){
		this.now = this.compute(this.from, this.to);
	},

	compute: function(from, to){
		return this.options.transition(this.cTime, from, (to - from), this.options.duration);
	},

	start: function(from, to){
		if (!this.options.wait) this.stop();
		else if (this.timer) return this;
		this.from = from;
		this.to = to;
		this.time = new Date().getTime();
		this.timer = this.step.periodical(Math.round(1000/this.options.fps), this);
		this.fireEvent('onStart', this.element);
		return this;
	},

	stop: function(end){
		if (!this.timer) return this;
		this.timer = $clear(this.timer);
		if (!end) this.fireEvent('onCancel', this.element);
		return this;
	},
	custom: function(from, to){return this.start(from, to)},
	clearTimer: function(end){return this.stop(end)}

});

Fx.Base.implement(new Chain);
Fx.Base.implement(new Events);
Fx.Base.implement(new Options);

Fx.Transitions = {
	linear: function(t, b, c, d){
		return c*t/d + b;
	},
	sineInOut: function(t, b, c, d){
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	}

};

Fx.CSS = {

	select: function(property, to){
		if (property.test(/color/i)) return this.Color;
		if (to.test && to.test(' ')) return this.Multi;
		return this.Single;
	},

	parse: function(el, property, fromTo){
		if (!fromTo.push) fromTo = [fromTo];
		var from = fromTo[0], to = fromTo[1];
		if (!to && to != 0){
			to = from;
			from = el.getStyle(property);
		}
		var css = this.select(property, to);
		return {from: css.parse(from), to: css.parse(to), css: css};
	}

};

Fx.CSS.Single = {

	parse: function(value){
		return parseFloat(value);
	},

	getNow: function(from, to, fx){
		return fx.compute(from, to);
	},

	getValue: function(value, unit){
		return value+unit;
	}

};

Fx.CSS.Multi = {

	parse: function(value){
		return value.push ? value : value.split(' ').map(function(v){
			return parseFloat(v);
		});
	},

	getNow: function(from, to, fx){
		var now = [];
		for (var i = 0; i < from.length; i++) now[i] = fx.compute(from[i], to[i]);
		return now;
	},

	getValue: function(value, unit){
		return value.join(unit+' ')+unit;
	}

};

Fx.CSS.Color = {

	parse: function(value){
		return value.push ? value : value.hexToRgb(true);
	},

	getNow: function(from, to, fx){
		var now = [];
		for (var i = 0; i < from.length; i++) now[i] = Math.round(fx.compute(from[i], to[i]));
		return now;
	},

	getValue: function(value){
		return 'rgb('+value.join(',')+')';
	}

};

Fx.Style = Fx.Base.extend({

	initialize: function(el, property, options){
		this.element = $(el);
		this.property = property;
		this.parent(options);
	},

	hide: function(){
		return this.set(0);
	},

	setNow: function(){
		this.now = this.css.getNow(this.from, this.to, this);
	},

	set: function(to){
		this.css = Fx.CSS.select(this.property, to);
		return this.parent(this.css.parse(to));
	},

	start: function(from, to){
		if (this.timer && this.options.wait) return this;
		var parsed = Fx.CSS.parse(this.element, this.property, [from, to]);
		this.css = parsed.css;
		return this.parent(parsed.from, parsed.to);
	},

	increase: function(){
		this.element.setStyle(this.property, this.css.getValue(this.now, this.options.unit));
	}

});

Element.extend({

	effect: function(property, options){
		return new Fx.Style(this, property, options);
	}

});

Fx.Styles = Fx.Base.extend({

	initialize: function(el, options){
		this.element = $(el);
		this.parent(options);
	},

	setNow: function(){
		for (var p in this.from) this.now[p] = this.css[p].getNow(this.from[p], this.to[p], this);
	},

	set: function(to){
		var parsed = {};
		this.css = {};
		for (var p in to){
			this.css[p] = Fx.CSS.select(p, to[p]);
			parsed[p] = this.css[p].parse(to[p]);
		}
		return this.parent(parsed);
	},

	start: function(obj){
		if (this.timer && this.options.wait) return this;
		this.now = {};
		this.css = {};
		var from = {}, to = {};
		for (var p in obj){
			var parsed = Fx.CSS.parse(this.element, p, obj[p]);
			from[p] = parsed.from;
			to[p] = parsed.to;
			this.css[p] = parsed.css;
		}
		return this.parent(from, to);
	},

	increase: function(){
		for (var p in this.now) this.element.setStyle(p, this.css[p].getValue(this.now[p], this.options.unit));
	}

});

Element.extend({

	effects: function(options){
		return new Fx.Styles(this, options);
	}

});

Fx.Elements = Fx.Base.extend({

	initialize: function(elements, options){
		this.elements = $$(elements);
		this.parent(options);
	},

	setNow: function(){
		for (var i in this.from){
			var iFrom = this.from[i], iTo = this.to[i], iCss = this.css[i], iNow = this.now[i] = {};
			for (var p in iFrom) iNow[p] = iCss[p].getNow(iFrom[p], iTo[p], this);
		}
	},

	set: function(to){
		var parsed = {};
		this.css = {};
		for (var i in to){
			var iTo = to[i], iCss = this.css[i] = {}, iParsed = parsed[i] = {};
			for (var p in iTo){
				iCss[p] = Fx.CSS.select(p, iTo[p]);
				iParsed[p] = iCss[p].parse(iTo[p]);
			}
		}
		return this.parent(parsed);
	},

	start: function(obj){
		if (this.timer && this.options.wait) return this;
		this.now = {};
		this.css = {};
		var from = {}, to = {};
		for (var i in obj){
			var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}, iCss = this.css[i] = {};
			for (var p in iProps){
				var parsed = Fx.CSS.parse(this.elements[i], p, iProps[p]);
				iFrom[p] = parsed.from;
				iTo[p] = parsed.to;
				iCss[p] = parsed.css;
			}
		}
		return this.parent(from, to);
	},

	increase: function(){
		for (var i in this.now){
			var iNow = this.now[i], iCss = this.css[i];
			for (var p in iNow) this.elements[i].setStyle(p, iCss[p].getValue(iNow[p], this.options.unit));
		}
	}

});

Fx.Scroll = Fx.Base.extend({

	initialize: function(element, options){
		this.now = [];
		this.element = $(element);
		this.addEvent('onStart', function(){
			this.element.addEvent('mousewheel', this.stop.bind(this, false));
		}.bind(this));
		this.removeEvent('onComplete', function(){
			this.element.removeEvent('mousewheel', this.stop.bind(this, false));
		}.bind(this));
		this.parent(options);
	},

	setNow: function(){
		for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
	},

	scrollTo: function(x, y){
		if (this.timer && this.options.wait) return this;
		var el = this.element.getSize();
		var values = {'x': x, 'y': y};
		for (var z in el.size){
			var max = el.scrollSize[z] - el.size[z];
			if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? Math.max(Math.min(values[z], max), 0) : max;
			else values[z] = el.scroll[z];
		}
		return this.start([el.scroll.x, el.scroll.y], [values.x, values.y]);
	},

	toTop: function(){
		return this.scrollTo(false, 0);
	},

	toBottom: function(){
		return this.scrollTo(false, 'full');
	},

	toLeft: function(){
		return this.scrollTo(0, false);
	},

	toRight: function(){
		return this.scrollTo('full', false);
	},

	toElement: function(el){
		return this.scrollTo($(el).getLeft(), $(el).getTop());
	},

	increase: function(){
		this.element.scrollTo(this.now[0], this.now[1]);
	}

});

Fx.Slide = Fx.Base.extend({

	initialize: function(el, options){
		this.element = $(el).setStyle('margin', 0);
		this.wrapper = new Element('div').injectAfter(this.element).setStyle('overflow', 'hidden').adopt(this.element);
		this.setOptions({'mode': 'vertical'}, options);
		this.now = [];
		this.parent(this.options);
	},

	setNow: function(){
		for (var i = 0; i < 2; i++) this.now[i] = this.compute(this.from[i], this.to[i]);
	},

	vertical: function(){
		this.margin = 'top';
		this.layout = 'height';
		this.offset = this.element.offsetHeight;
		return [this.element.getStyle('margin-top').toInt(), this.wrapper.getStyle('height').toInt()];
	},

	horizontal: function(){
		this.margin = 'left';
		this.layout = 'width';
		this.offset = this.element.offsetWidth;
		return [this.element.getStyle('margin-left').toInt(), this.wrapper.getStyle('width').toInt()];
	},

	slideIn: function(mode){
		return this.start(this[mode || this.options.mode](), [0, this.offset]);
	},

	slideOut: function(mode){
		return this.start(this[mode || this.options.mode](), [-this.offset, 0]);
	},

	hide: function(mode){
		this[mode || this.options.mode]();
		return this.set([-this.offset, 0]);
	},

	show: function(mode){
		this[mode || this.options.mode]();
		return this.set([0, this.offset]);
	},

	toggle: function(mode){
		if (this.wrapper.offsetHeight == 0 || this.wrapper.offsetWidth == 0) return this.slideIn(mode);
		else return this.slideOut(mode);
	},

	increase: function(){
		this.element.setStyle('margin-'+this.margin, this.now[0]+this.options.unit);
		this.wrapper.setStyle(this.layout, this.now[1]+this.options.unit);
	}

});

Fx.Transitions = {
	linear: function(t, b, c, d){
		return c*t/d + b;
	},
	quadIn: function(t, b, c, d){
		return c*(t/=d)*t + b;
	},
	quadOut: function(t, b, c, d){
		return -c *(t/=d)*(t-2) + b;
	},
	quadInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	cubicIn: function(t, b, c, d){
		return c*(t/=d)*t*t + b;
	},
	cubicOut: function(t, b, c, d){
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	cubicInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	quartIn: function(t, b, c, d){
		return c*(t/=d)*t*t*t + b;
	},
	quartOut: function(t, b, c, d){
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	quartInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	quintIn: function(t, b, c, d){
		return c*(t/=d)*t*t*t*t + b;
	},
	quintOut: function(t, b, c, d){
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	quintInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	sineIn: function(t, b, c, d){
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	sineOut: function(t, b, c, d){
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	sineInOut: function(t, b, c, d){
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	expoIn: function(t, b, c, d){
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	expoOut: function(t, b, c, d){
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	expoInOut: function(t, b, c, d){
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	circIn: function(t, b, c, d){
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	circOut: function(t, b, c, d){
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	circInOut: function(t, b, c, d){
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	elasticIn: function(t, b, c, d, a, p){
		if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a) a = 1;
		if (a < Math.abs(c)){ a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin(c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	elasticOut: function(t, b, c, d, a, p){
		if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (!a) a = 1;
		if (a < Math.abs(c)){ a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin(c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	elasticInOut: function(t, b, c, d, a, p){
		if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); if (!a) a = 1;
		if (a < Math.abs(c)){ a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin(c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	backIn: function(t, b, c, d, s){
		if (!s) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	backOut: function(t, b, c, d, s){
		if (!s) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	backInOut: function(t, b, c, d, s){
		if (!s) s = 1.70158;
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	bounceIn: function(t, b, c, d){
		return c - Fx.Transitions.bounceOut (d-t, 0, c, d) + b;
	},
	bounceOut: function(t, b, c, d){
		if ((t/=d) < (1/2.75)){
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)){
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)){
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	bounceInOut: function(t, b, c, d){
		if (t < d/2) return Fx.Transitions.bounceIn(t*2, 0, c, d) * .5 + b;
		return Fx.Transitions.bounceOut(t*2-d, 0, c, d) * .5 + c*.5 + b;
	}

};

var Drag = {};

Drag.Base = new Class({

	getOptions: function(){
		return {
			handle: false,
			unit: 'px',
			onStart: Class.empty,
			onBeforeStart: Class.empty,
			onComplete: Class.empty,
			onSnap: Class.empty,
			onDrag: Class.empty,
			limit: false,
			modifiers: {x: 'left', y: 'top'},
			snap: 6
		};
	},

	initialize: function(el, options){
		this.setOptions(this.getOptions(), options);
		this.element = $(el);
		this.handle = $(this.options.handle) || this.element;
		this.mouse = {'now': {}, 'pos': {}};
		this.value = {'start': {}, 'now': {}};
		this.bound = {'start': this.start.bindWithEvent(this)};
		this.attach();
		if (this.options.initialize) this.options.initialize.call(this);
	},

	attach: function(){
		this.handle.addEvent('mousedown', this.bound.start);
	},

	start: function(event){
		this.fireEvent('onBeforeStart', this.element);
		this.mouse.start = event.page;
		var limit = this.options.limit;
		this.limit = {'x': [], 'y': []};
		for (var z in this.options.modifiers){
			this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
			this.mouse.pos[z] = event.page[z] - this.value.now[z];
			if (limit && limit[z]){
				for (var i = 0; i < 2; i++){
					if ($chk(limit[z][i])) this.limit[z][i] = limit[z][i].apply ? limit[z][i].call(this) : limit[z][i];
				}
			}
		}
		this.bound.drag = this.drag.bindWithEvent(this);
		this.bound.stop = this.stop.bind(this);
		this.bound.move = this.options.snap ? this.checkAndDrag.bindWithEvent(this) : this.bound.drag;
		document.addEvent('mousemove', this.bound.move);
		document.addEvent('mouseup', this.bound.stop);
		this.fireEvent('onStart', this.element);
		event.stop();
	},

	checkAndDrag: function(event){
		var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
		if (distance > this.options.snap){
			document.removeEvent('mousemove', this.bound.move);
			this.bound.move = this.bound.drag;
			document.addEvent('mousemove', this.bound.move);
			this.drag(event);
			this.fireEvent('onSnap', this.element);
		}
		event.stop();
	},

	drag: function(event){
		this.out = false;
		this.mouse.now = event.page;
		for (var z in this.options.modifiers){
			this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
			if (this.limit[z]){
				if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){
					this.value.now[z] = this.limit[z][1];
					this.out = true;
				} else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){
					this.value.now[z] = this.limit[z][0];
					this.out = true;
				}
			}
			this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
		}
		this.fireEvent('onDrag', this.element);
		event.stop();
	},

	detach: function(){
		this.handle.removeEvent('mousedown', this.bound.start);
	},

	stop: function(){
		document.removeEvent('mousemove', this.bound.move);
		document.removeEvent('mouseup', this.bound.stop);
		this.fireEvent('onComplete', this.element);
	}

});

Drag.Base.implement(new Events);
Drag.Base.implement(new Options);

Element.extend({

	makeResizable: function(options){
		return new Drag.Base(this, Object.extend(options || {}, {modifiers: {x: 'width', y: 'height'}}));
	}

});

Drag.Move = Drag.Base.extend({

	getExtended: function(){
		return {
			droppables: [],
			container: false,
			overflown: []
		}
	},

	initialize: function(el, options){
		this.setOptions(this.getExtended(), options);
		this.element = $(el);
		this.position = this.element.getStyle('position');
		this.droppables = $$(this.options.droppables);
		if (!['absolute', 'relative'].test(this.position)) this.position = 'absolute';
		var top = this.element.getStyle('top').toInt();
		var left = this.element.getStyle('left').toInt();
		if (this.position == 'absolute'){
			top = $chk(top) ? top : this.element.getTop();
			left = $chk(left) ? left : this.element.getLeft();
		} else {
			top = $chk(top) ? top : 0;
			left = $chk(left) ? left : 0;
		}
		this.element.setStyles({
			'top': top+'px',
			'left': left+'px',
			'position': this.position
		});
		this.parent(this.element, this.options);
	},

	start: function(event){
		this.container = $(this.options.container);
		if (this.container){
			var cont = this.container.getCoordinates();
			var el = this.element.getCoordinates();
			if (this.position == 'absolute'){
				this.options.limit = {
					'x': [cont.left, cont.right - el.width],
					'y': [cont.top, cont.bottom - el.height]
				};
			} else {
				var diffx = el.left - this.element.getStyle('left').toInt();
				var diffy = el.top - this.element.getStyle('top').toInt();
				this.options.limit = {
					'y': [-(diffy) + cont.top, cont.bottom - diffy - el.height],
					'x': [-(diffx) + cont.left, cont.right - diffx - el.width]
				};
			}
		}
		this.parent(event);
	},

	drag: function(event){
		this.parent(event);
		if (this.out) return this;
		this.droppables.each(function(drop){
			if (this.checkAgainst($(drop))){
				if (!drop.overing) drop.fireEvent('over', [this.element, this]);
				drop.overing = true;
			} else {
				if (drop.overing) drop.fireEvent('leave', [this.element, this]);
				drop.overing = false;
			}
		}, this);
		return this;
	},

	checkAgainst: function(el){
		el = el.getCoordinates(this.options.overflown);
		return (this.mouse.now.x > el.left && this.mouse.now.x < el.right && this.mouse.now.y < el.bottom && this.mouse.now.y > el.top);
	},

	stop: function(){
		this.parent();
		this.timer = $clear(this.timer);
		if (this.out) return this;
		var dropped = false;
		this.droppables.each(function(drop){
			if (this.checkAgainst(drop)){
				drop.fireEvent('drop', [this.element, this]);
				dropped = true;
			}
		}, this);
		if (!dropped) this.element.fireEvent('drop', this);
		return this;
	}

});

Element.extend({

	makeDraggable: function(options){
		return new Drag.Move(this, options);
	}

});

var XHR = new Class({

	getOptions: function(){
		return {
			method: 'post',
			async: true,
			onRequest: Class.empty,
			onStateChange: Class.empty,
			onSuccess: Class.empty,
			onFailure: Class.empty,
			headers: {},
			isSuccess: this.isSuccess
		}
	},

	initialize: function(options){
		this.transport = window.XMLHttpRequest ? new XMLHttpRequest() : (window.ie ? new ActiveXObject('Microsoft.XMLHTTP') : false);
		this.setOptions(this.getOptions(), options);
		if (!this.transport) return;
		this.headers = {};
		if (this.options.initialize) this.options.initialize.call(this);
	},

	onStateChange: function(){
		this.fireEvent('onStateChange', this.transport);
		if (this.transport.readyState != 4) return;
		var status = 0;
		try {status = this.transport.status} catch (e){}
		if (this.options.isSuccess(status)) this.onSuccess();
		else this.onFailure();
		this.transport.onreadystatechange = Class.empty;
	},

	isSuccess: function(status){
		return ((status >= 200) && (status < 300));
	},

	onSuccess: function(){
		this.response = {
			'text': this.transport.responseText,
			'xml': this.transport.responseXML
		};
		this.fireEvent('onSuccess', [this.response.text, this.response.xml]);
		this.callChain();
	},

	onFailure: function(){
		this.fireEvent('onFailure', this.transport);
	},

	setHeader: function(name, value){
		this.headers[name] = value;
		return this;
	},

	send: function(url, data){
		this.fireEvent('onRequest');
		this.transport.open(this.options.method, url, this.options.async);
		this.transport.onreadystatechange = this.onStateChange.bind(this);
		if ((this.options.method == 'post') && this.transport.overrideMimeType) this.setHeader('Connection', 'close');
		Object.extend(this.headers, this.options.headers);
		for (var type in this.headers) this.transport.setRequestHeader(type, this.headers[type]);
		this.transport.send(data);
		return this;
	}

});

XHR.implement(new Chain);
XHR.implement(new Events);
XHR.implement(new Options);

var Ajax = XHR.extend({

	moreOptions: function(){
		return {
			postBody: null,
			update: null,
			onComplete: Class.empty,
			evalScripts: false,
			evalResponse: false,
			encoding: 'utf-8'
		};
	},

	initialize: function(url, options){
		this.addEvent('onSuccess', this.onComplete);
		this.setOptions(this.moreOptions(), options);
		this.parent(this.options);
		if (!['post', 'get'].test(this.options.method)){
			this._method = '_method='+this.options.method;
			this.options.method = 'post';
		}
		if (this.options.method == 'post'){
			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
			this.setHeader('Content-type', 'application/x-www-form-urlencoded' + encoding);
		}
		this.setHeader('X-Requested-With', 'XMLHttpRequest');
		this.setHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
		this.url = url;
	},

	onComplete: function(){
		if (this.options.update) $(this.options.update).setHTML(this.response.text);
		if (this.options.evalResponse) eval(this.response.text);
		if (this.options.evalScripts) this.evalScripts.delay(30, this);
		this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
	},

	request: function(){
		var data = null;
		switch ($type(this.options.postBody)){
			case 'element': data = $(this.options.postBody).toQueryString(); break;
			case 'object': data = Object.toQueryString(this.options.postBody); break;
			case 'string': data = this.options.postBody;
		}
		if (this._method) data = (data) ? [this._method, data].join('&') : this._method;
		return this.send(this.url, data);
	},

	evalScripts: function(){
		var script, regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi;
		while ((script = regexp.exec(this.response.text))) eval(script[1]);
	}

});

Object.toQueryString = function(source){
	var queryString = [];
	for (var property in source) queryString.push(encodeURIComponent(property)+'='+encodeURIComponent(source[property]));
	return queryString.join('&');
};

Element.extend({

	send: function(options){
		options = Object.extend(options || {}, {postBody: this.toQueryString(), method: 'post'});
		return new Ajax(this.getProperty('action'), options).request();
	},

	toObject: function(){
		var obj = {};
		$$(this.getElementsByTagName('input'), this.getElementsByTagName('select'), this.getElementsByTagName('textarea')).each(function(el){
			var name = $(el).name;
			var value = el.getValue();
			if ((value !== false) && name) obj[name] = value;
		});
		return obj;
	},

	toQueryString: function(){
		return Object.toQueryString(this.toObject());
	}

});

var Cookie = {

	set: function(key, value, options){
		options = Object.extend({
			domain: false,
			path: false,
			duration: 365
		}, options || {});
		value = escape(value);
		if (options.domain) value += "; domain=" + options.domain;
		if (options.path) value += "; path=" + options.path;
		if (options.duration){
			var date = new Date();
			date.setTime(date.getTime() + (options.duration * 86400000));
			value += "; expires=" + date.toGMTString();
		}
		document.cookie = key + "=" + value;
	},

	get: function(key){
		var value = document.cookie.match('(?:^|;)\\s*'+key+'=([^;]*)');
		return value ? unescape(value[1]) : false;
	},

	remove: function(key){
		this.set(key, '', {duration: -1});
	}

};

var Json = {

	toString: function(obj){
		switch ($type(obj)){
			case 'string':
				return '"'+obj.replace(new RegExp('(["\\\\])', 'g'), '\\$1')+'"';
			case 'array':
				return '['+ obj.map(function(ar){
					return Json.toString(ar);
				}).join(',') +']';
			case 'object':
				var string = [];
				for (var property in obj) string.push('"'+property+'":'+Json.toString(obj[property]));
				return '{'+string.join(',')+'}';
		}
		return String(obj);
	},

	evaluate: function(str){
		return eval('(' + str + ')');
	}

};

Json.Remote = XHR.extend({

	initialize: function(url, options){
		this.url = url;
		this.addEvent('onSuccess', this.onComplete);
		this.parent(options);
		this.setHeader('X-Request', 'JSON');
	},

	send: function(obj){
		return this.parent(this.url, 'json='+Json.toString(obj));
	},

	onComplete: function(){
		this.fireEvent('onComplete', Json.evaluate(this.response.text));
	}

});

var Asset = {

	javascript: function(source, properties){
		return Asset.create('script', {
			'type': 'text/javascript', 'src': source
		}, properties, true);
	},

	css: function(source, properties){
		return Asset.create('link', {
			'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source
		}, properties, true);
	},

	image: function(source, properties){
		properties = Object.extend({
			'src': source,
			'onload': Class.empty,
			'onabort': Class.empty,
			'onerror': Class.empty
		}, properties || {});
		var image = new Image();
		image.onload = function(){
			if (arguments.callee.done) return false;
			arguments.callee.done = true;
			this.onload = null;
			return properties.onload.call(this);
		};
		image.onerror = properties.onerror;
		image.onabort = properties.onabort;
		image.src = properties.src;
		return Asset.create('img', properties);
	},

	images: function(sources, options){
		options = Object.extend({
			onComplete: Class.empty,
			onProgress: Class.empty
		}, options || {});
		if (!sources.push) sources = [sources];
		var images = [];
		counter = 0;
		sources.each(function(source){
			var img = new Asset.image(source, {
				'onload': function(){
					counter++;
					options.onProgress();
					if (counter == sources.length) options.onComplete();
				}
			});
			images.push(img);
		});
		return images;
	},

	create: function(type, defaults, properties, inject){
		Object.extend(defaults, properties || {});
		var element = new Element(type).setProperties(defaults);
		if (inject) element.injectInside($$('head')[0]);
		return element;
	}

};

var Scroller = new Class({

	getOptions: function(){
		return {
			area: 20,
			velocity: 1,
			onChange: function(x, y){
				this.element.scrollTo(x, y);
			}
		};
	},

	initialize: function(element, options){
		this.setOptions(this.getOptions(), options);
		this.element = $(element);
		this.mousemover = ([window, document].test(element)) ? $(document.body) : this.element;
	},

	start: function(){
		this.coord = this.getCoords.bindWithEvent(this);
		this.mousemover.addEvent('mousemove', this.coord);
	},

	stop: function(){
		this.mousemover.removeEvent('mousemove', this.coord);
		this.timer = $clear(this.timer);
	},

	getCoords: function(event){
		this.page = (this.element == window) ? event.client : event.page;
		if (!this.timer) this.timer = this.scroll.periodical(50, this);
	},

	scroll: function(){
		var el = this.element.getSize();
		var pos = this.element.getPosition();

		var change = {'x': 0, 'y': 0};
		for (var z in this.page){
			if (this.page[z] < (this.options.area + pos[z]) && el.scroll[z] != 0)
				change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
			else if (this.page[z] + this.options.area > (el.size[z] + pos[z]) && el.scroll[z] + el.size[z] != el.scrollSize[z])
				change[z] = (this.page[z] - el.size[z] + this.options.area - pos[z]) * this.options.velocity;
		}
		if (change.y || change.x) this.fireEvent('onChange', [el.scroll.x + change.x, el.scroll.y + change.y]);
	}

});

Scroller.implement(new Events);
Scroller.implement(new Options);

var Slider = new Class({

	getOptions: function(){
		return {
			onChange: Class.empty,
			onComplete: Class.empty,
			onTick: function(pos){
				this.knob.setStyle(this.p, pos+'px');
			},
			steps: 100,
			mode: 'horizontal',
			wheel: false
		};
	},

	initialize: function(el, knob, options){
		this.element = $(el);
		this.knob = $(knob);
		this.setOptions(this.getOptions(), options);

		this.previousChange = -1;
		this.previousEnd = -1;
		this.step = -1;

		this.element.addEvent('mousedown', this.clickedElement.bindWithEvent(this));

		if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement.bindWithEvent(this));

		if (this.options.mode == 'horizontal'){
			this.z = 'x'; this.p = 'left';
			this.max = this.element.offsetWidth-this.knob.offsetWidth;
			this.half = this.knob.offsetWidth/2;
			this.getPos = this.element.getLeft.bind(this.element);
		} else if (this.options.mode == 'vertical'){
			this.z = 'y'; this.p = 'top';
			this.max = this.element.offsetHeight-this.knob.offsetHeight;
			this.half = this.knob.offsetHeight/2;
			this.getPos = this.element.getTop.bind(this.element);
		}

		this.knob.setStyle('position', 'relative').setStyle(this.p, 0);

		var modSlide = {}, limSlide = {};

		limSlide[this.z] = [0, this.max];
		modSlide[this.z] = this.p;

		this.drag = new Drag.Base(this.knob, {
			limit: limSlide,
			snap: 0,
			modifiers: modSlide,
			onStart: function(){
				this.draggedKnob();
			}.bind(this),
			onDrag: function(){
				this.draggedKnob();
			}.bind(this),
			onComplete: function(){
				this.draggedKnob();
				this.end();
			}.bind(this)
		});
		if (this.options.initialize) this.options.initialize.call(this);
	},

	set: function(step){
		if (step > this.options.steps) step = this.options.steps;
		else if (step < 0) step = 0;
		this.step = step;
		this.checkStep();
		this.end();
		this.fireEvent('onTick', this.toPosition(this.step)+'');
		return this;
	},

	scrolledElement: function(event){
		if (event.wheel < 0) this.set(this.step + 1);
		else if (event.wheel > 0) this.set(this.step - 1);
		event.stop();
	},

	clickedElement: function(event){
		var position = event.page[this.z] - this.getPos() - this.half;
		if (position > this.max) position = this.max;
		else if (position < 0) position = 0;
		this.step = this.toStep(position);
		this.checkStep();
		this.end();
		this.fireEvent('onTick', position+'');
	},

	draggedKnob: function(){
		this.step = this.toStep(this.drag.value.now[this.z]);
		this.checkStep();
	},

	checkStep: function(){
		if (this.previousChange != this.step){
			this.previousChange = this.step;
			this.fireEvent('onChange', this.step);
		}
	},

	end: function(){
		if (this.previousEnd !== this.step){
			this.previousEnd = this.step;
			this.fireEvent('onComplete', this.step+'');
		}
	},

	toStep: function(position){
		return Math.round(position/this.max*this.options.steps);
	},

	toPosition: function(step){
		return (this.max)*step/this.options.steps;
	}

});

Slider.implement(new Events);
Slider.implement(new Options);

var SmoothScroll = Fx.Scroll.extend({

	initialize: function(options){
		this.addEvent('onCancel', this.clearChain);
		var location = window.location.href.match(/^[^#]*/)[0] + '#';
		$each(document.links, function(lnk){
			if (lnk.href.indexOf(location) != 0) return;
			var anchor = lnk.href.substr(location.length);
			if (anchor && $(anchor)) this.useLink(lnk, anchor);
		}, this);
		this.parent(window, options);
	},

	useLink: function(lnk, anchor){
		lnk.addEvent('click', function(event){
			if(!window.khtml) this.chain(function(){
				window.location.href = '#'+anchor;
			});
			this.toElement(anchor);
			event.stop();
		}.bindWithEvent(this));
	}

});

var Sortables = new Class({

	getOptions: function() {
		return {
			handles: false,
			onStart: Class.empty,
			onComplete: Class.empty,
			ghost: true,
			snap: 3,
			onDragStart: function(element, ghost){
				ghost.setStyle('opacity', 0.5);
			},
			onDragComplete: function(element, ghost){
				ghost.remove();
			}
		};
	},

	initialize: function(list, options){
		this.setOptions(this.getOptions(), options);
		this.list = $(list);
		this.elements = this.list.getChildren();
		this.handles = $$(this.options.handles) || this.elements;
		this.drag = [];
		this.bound = {'start': []};
		this.elements.each(function(el, i){
			this.bound.start[i] = this.start.bindWithEvent(this, el);
			if (this.options.ghost){
				this.trash = new Element('div').injectInside(document.body);
				var limit = this.list.getCoordinates();
				this.drag[i] = new Drag.Base(el, {
					handle: this.handles[i],
					snap: this.options.snap,
					modifiers: {y: 'top'},
					limit: {y: [limit.top, limit.bottom - el.offsetHeight]},
					onBeforeStart: function(element){
						var offsets = element.getPosition();
						this.old = element;
						this.drag[i].element = this.ghost = element.clone().setStyles({
							'position': 'absolute',
							'top': offsets.y+'px',
							'left': offsets.x+'px'
						}).injectInside(this.trash);
						this.fireEvent('onDragStart', [el, this.ghost]);
					}.bind(this),
					onComplete: function(element){
						this.drag[i].element = this.old;
						this.fireEvent('onDragComplete', [el, this.ghost]);
					}.bind(this)
				});
			}
			this.handles[i].addEvent('mousedown', this.start.bindWithEvent(this, el));
		}, this);
		if (this.options.initialize) this.options.initialize.call(this);
	},

	start: function(event, el){
		this.bound.move = this.move.bindWithEvent(this, el);
		this.bound.end = this.end.bind(this, el);
		document.addEvent('mousemove', this.bound.move);
		document.addEvent('mouseup', this.bound.end);
		this.fireEvent('onStart', el);
		event.stop();
	},

	move: function(event, el){
		var prev = el.getPrevious();
		var next = el.getNext();
		if (prev){
			var prevPos = prev.getCoordinates();
			if (event.page.y < prevPos.bottom) el.injectBefore(prev);
		}
		if (next){
			var nextPos = next.getCoordinates();
			if (event.page.y > nextPos.top) el.injectAfter(next);
		}
		event.stop();
	},

	detach: function(){
		this.elements.each(function(el, i){
			this.handles[i].removeEvent('mousedown', this.bound.start[i]);
		}, this);
	},

	serialize: function(){
		var serial = [];
		this.list.getChildren().each(function(el, i){
			serial[i] = this.elements.indexOf(el);
		}, this);
		return serial;
	},

	end: function(el){
		document.removeEvent('mousemove', this.bound.move);
		document.removeEvent('mouseup', this.bound.end);
		this.fireEvent('onComplete', el);
	}

});

Sortables.implement(new Events);
Sortables.implement(new Options);

var Tips = new Class({

	getOptions: function(){
		return {
			onShow: function(tip){
				tip.setStyle('visibility', 'visible');
			},
			onHide: function(tip){
				tip.setStyle('visibility', 'hidden');
			},
			maxTitleChars: 30,
			showDelay: 100,
			hideDelay: 100,
			className: 'tool',
			offsets: {'x': 16, 'y': 16},
			fixed: false
		};
	},

	initialize: function(elements, options){
		this.setOptions(this.getOptions(), options);
		this.toolTip = new Element('div').addClass(this.options.className+'-tip').setStyles({
			'position': 'absolute',
			'top': '0',
			'left': '0',
			'visibility': 'hidden'
		}).injectInside(document.body);
		this.wrapper = new Element('div').injectInside(this.toolTip);
		$each(elements, function(el){
			this.build($(el));
		}, this);
		if (this.options.initialize) this.options.initialize.call(this);
	},

	build: function(el){
		el.myTitle = el.href ? el.href.replace('http://', '') : (el.rel || false);
		if (el.title){
			var dual = el.title.split('::');
			if (dual.length > 1) {
				el.myTitle = dual[0].trim();
				el.myText = dual[1].trim();
			} else {
				el.myText = el.title;
			}
			el.removeAttribute('title');
		} else {
			el.myText = false;
		}
		if (el.myTitle && el.myTitle.length > this.options.maxTitleChars) el.myTitle = el.myTitle.substr(0, this.options.maxTitleChars - 1) + "&hellip;";
		el.addEvent('mouseover', function(event){
			this.start(el);
			this.locate(event);
		}.bindWithEvent(this));
		if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this));
		el.addEvent('mouseout', this.end.bindWithEvent(this));
	},

	start: function(el){
		this.wrapper.setHTML('');
		if (el.myTitle){
			new Element('span').injectInside(
				new Element('div').addClass(this.options.className+'-title').injectInside(this.wrapper)
			).setHTML(el.myTitle);
		}
		if (el.myText){
			new Element('span').injectInside(
				new Element('div').addClass(this.options.className+'-text').injectInside(this.wrapper)
			).setHTML(el.myText);
		}
		$clear(this.timer);
		this.timer = this.show.delay(this.options.showDelay, this);
	},

	end: function(event){
		$clear(this.timer);
		this.timer = this.hide.delay(this.options.hideDelay, this);
		event.stop();
	},

	locate: function(event){
		var win = {'x': window.getWidth(), 'y': window.getHeight()};
		var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()};
		var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight};
		var prop = {'x': 'left', 'y': 'top'};
		for (var z in prop){
			var pos = event.page[z] + this.options.offsets[z];
			if ((pos + tip[z] - scroll[z]) > win[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
			this.toolTip.setStyle(prop[z], pos + 'px');
		};
		event.stop();
	},

	show: function(){
		this.fireEvent('onShow', [this.toolTip]);
	},

	hide: function(){
		this.fireEvent('onHide', [this.toolTip]);
	}

});

Tips.implement(new Events);
Tips.implement(new Options);


/*	SWFObject v2.0 <http://code.google.com/p/swfobject/>
	Copyright (c) 2007 Geoff Stearns, Michael Williams, and Bobby van der Sluis
	This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject=function(){var Z="undefined",P="object",B="Shockwave Flash",h="ShockwaveFlash.ShockwaveFlash",W="application/x-shockwave-flash",K="SWFObjectExprInst",G=window,g=document,N=navigator,f=[],H=[],Q=null,L=null,T=null,S=false,C=false;var a=function(){var l=typeof g.getElementById!=Z&&typeof g.getElementsByTagName!=Z&&typeof g.createElement!=Z&&typeof g.appendChild!=Z&&typeof g.replaceChild!=Z&&typeof g.removeChild!=Z&&typeof g.cloneNode!=Z,t=[0,0,0],n=null;if(typeof N.plugins!=Z&&typeof N.plugins[B]==P){n=N.plugins[B].description;if(n){n=n.replace(/^.*\s+(\S+\s+\S+$)/,"$1");t[0]=parseInt(n.replace(/^(.*)\..*$/,"$1"),10);t[1]=parseInt(n.replace(/^.*\.(.*)\s.*$/,"$1"),10);t[2]=/r/.test(n)?parseInt(n.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof G.ActiveXObject!=Z){var o=null,s=false;try{o=new ActiveXObject(h+".7")}catch(k){try{o=new ActiveXObject(h+".6");t=[6,0,21];o.AllowScriptAccess="always"}catch(k){if(t[0]==6){s=true}}if(!s){try{o=new ActiveXObject(h)}catch(k){}}}if(!s&&o){try{n=o.GetVariable("$version");if(n){n=n.split(" ")[1].split(",");t=[parseInt(n[0],10),parseInt(n[1],10),parseInt(n[2],10)]}}catch(k){}}}}var v=N.userAgent.toLowerCase(),j=N.platform.toLowerCase(),r=/webkit/.test(v)?parseFloat(v.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,i=false,q=j?/win/.test(j):/win/.test(v),m=j?/mac/.test(j):/mac/.test(v);/*@cc_on i=true;@if(@_win32)q=true;@elif(@_mac)m=true;@end@*/return{w3cdom:l,pv:t,webkit:r,ie:i,win:q,mac:m}}();var e=function(){if(!a.w3cdom){return }J(I);if(a.ie&&a.win){try{g.write("<script id=__ie_ondomload defer=true src=//:><\/script>");var i=c("__ie_ondomload");if(i){i.onreadystatechange=function(){if(this.readyState=="complete"){this.parentNode.removeChild(this);V()}}}}catch(j){}}if(a.webkit&&typeof g.readyState!=Z){Q=setInterval(function(){if(/loaded|complete/.test(g.readyState)){V()}},10)}if(typeof g.addEventListener!=Z){g.addEventListener("DOMContentLoaded",V,null)}M(V)}();function V(){if(S){return }if(a.ie&&a.win){var m=Y("span");try{var l=g.getElementsByTagName("body")[0].appendChild(m);l.parentNode.removeChild(l)}catch(n){return }}S=true;if(Q){clearInterval(Q);Q=null}var j=f.length;for(var k=0;k<j;k++){f[k]()}}function J(i){if(S){i()}else{f[f.length]=i}}function M(j){if(typeof G.addEventListener!=Z){G.addEventListener("load",j,false)}else{if(typeof g.addEventListener!=Z){g.addEventListener("load",j,false)}else{if(typeof G.attachEvent!=Z){G.attachEvent("onload",j)}else{if(typeof G.onload=="function"){var i=G.onload;G.onload=function(){i();j()}}else{G.onload=j}}}}}function I(){var l=H.length;for(var j=0;j<l;j++){var m=H[j].id;if(a.pv[0]>0){var k=c(m);if(k){H[j].width=k.getAttribute("width")?k.getAttribute("width"):"0";H[j].height=k.getAttribute("height")?k.getAttribute("height"):"0";if(O(H[j].swfVersion)){if(a.webkit&&a.webkit<312){U(k)}X(m,true)}else{if(H[j].expressInstall&&!C&&O("6.0.65")&&(a.win||a.mac)){D(H[j])}else{d(k)}}}}else{X(m,true)}}}function U(m){var k=m.getElementsByTagName(P)[0];if(k){var p=Y("embed"),r=k.attributes;if(r){var o=r.length;for(var n=0;n<o;n++){if(r[n].nodeName.toLowerCase()=="data"){p.setAttribute("src",r[n].nodeValue)}else{p.setAttribute(r[n].nodeName,r[n].nodeValue)}}}var q=k.childNodes;if(q){var s=q.length;for(var l=0;l<s;l++){if(q[l].nodeType==1&&q[l].nodeName.toLowerCase()=="param"){p.setAttribute(q[l].getAttribute("name"),q[l].getAttribute("value"))}}}m.parentNode.replaceChild(p,m)}}function F(i){if(a.ie&&a.win&&O("8.0.0")){G.attachEvent("onunload",function(){var k=c(i);if(k){for(var j in k){if(typeof k[j]=="function"){k[j]=function(){}}}k.parentNode.removeChild(k)}})}}function D(j){C=true;var o=c(j.id);if(o){if(j.altContentId){var l=c(j.altContentId);if(l){L=l;T=j.altContentId}}else{L=b(o)}if(!(/%$/.test(j.width))&&parseInt(j.width,10)<310){j.width="310"}if(!(/%$/.test(j.height))&&parseInt(j.height,10)<137){j.height="137"}g.title=g.title.slice(0,47)+" - Flash Player Installation";var n=a.ie&&a.win?"ActiveX":"PlugIn",k=g.title,m="MMredirectURL="+G.location+"&MMplayerType="+n+"&MMdoctitle="+k,p=j.id;if(a.ie&&a.win&&o.readyState!=4){var i=Y("div");p+="SWFObjectNew";i.setAttribute("id",p);o.parentNode.insertBefore(i,o);o.style.display="none";G.attachEvent("onload",function(){o.parentNode.removeChild(o)})}R({data:j.expressInstall,id:K,width:j.width,height:j.height},{flashvars:m},p)}}function d(j){if(a.ie&&a.win&&j.readyState!=4){var i=Y("div");j.parentNode.insertBefore(i,j);i.parentNode.replaceChild(b(j),i);j.style.display="none";G.attachEvent("onload",function(){j.parentNode.removeChild(j)})}else{j.parentNode.replaceChild(b(j),j)}}function b(n){var m=Y("div");if(a.win&&a.ie){m.innerHTML=n.innerHTML}else{var k=n.getElementsByTagName(P)[0];if(k){var o=k.childNodes;if(o){var j=o.length;for(var l=0;l<j;l++){if(!(o[l].nodeType==1&&o[l].nodeName.toLowerCase()=="param")&&!(o[l].nodeType==8)){m.appendChild(o[l].cloneNode(true))}}}}}return m}function R(AE,AC,q){var p,t=c(q);if(typeof AE.id==Z){AE.id=q}if(a.ie&&a.win){var AD="";for(var z in AE){if(AE[z]!=Object.prototype[z]){if(z=="data"){AC.movie=AE[z]}else{if(z.toLowerCase()=="styleclass"){AD+=' class="'+AE[z]+'"'}else{if(z!="classid"){AD+=" "+z+'="'+AE[z]+'"'}}}}}var AB="";for(var y in AC){if(AC[y]!=Object.prototype[y]){AB+='<param name="'+y+'" value="'+AC[y]+'" />'}}t.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AD+">"+AB+"</object>";F(AE.id);p=c(AE.id)}else{if(a.webkit&&a.webkit<312){var AA=Y("embed");AA.setAttribute("type",W);for(var x in AE){if(AE[x]!=Object.prototype[x]){if(x=="data"){AA.setAttribute("src",AE[x])}else{if(x.toLowerCase()=="styleclass"){AA.setAttribute("class",AE[x])}else{if(x!="classid"){AA.setAttribute(x,AE[x])}}}}}for(var w in AC){if(AC[w]!=Object.prototype[w]){if(w!="movie"){AA.setAttribute(w,AC[w])}}}t.parentNode.replaceChild(AA,t);p=AA}else{var s=Y(P);s.setAttribute("type",W);for(var v in AE){if(AE[v]!=Object.prototype[v]){if(v.toLowerCase()=="styleclass"){s.setAttribute("class",AE[v])}else{if(v!="classid"){s.setAttribute(v,AE[v])}}}}for(var u in AC){if(AC[u]!=Object.prototype[u]&&u!="movie"){E(s,u,AC[u])}}t.parentNode.replaceChild(s,t);p=s}}return p}function E(k,i,j){var l=Y("param");l.setAttribute("name",i);l.setAttribute("value",j);k.appendChild(l)}function c(i){return g.getElementById(i)}function Y(i){return g.createElement(i)}function O(k){var j=a.pv,i=k.split(".");i[0]=parseInt(i[0],10);i[1]=parseInt(i[1],10);i[2]=parseInt(i[2],10);return(j[0]>i[0]||(j[0]==i[0]&&j[1]>i[1])||(j[0]==i[0]&&j[1]==i[1]&&j[2]>=i[2]))?true:false}function A(m,j){if(a.ie&&a.mac){return }var l=g.getElementsByTagName("head")[0],k=Y("style");k.setAttribute("type","text/css");k.setAttribute("media","screen");if(!(a.ie&&a.win)&&typeof g.createTextNode!=Z){k.appendChild(g.createTextNode(m+" {"+j+"}"))}l.appendChild(k);if(a.ie&&a.win&&typeof g.styleSheets!=Z&&g.styleSheets.length>0){var i=g.styleSheets[g.styleSheets.length-1];if(typeof i.addRule==P){i.addRule(m,j)}}}function X(k,i){var j=i?"visible":"hidden";if(S){c(k).style.visibility=j}else{A("#"+k,"visibility:"+j)}}return{registerObject:function(l,i,k){if(!a.w3cdom||!l||!i){return }var j={};j.id=l;j.swfVersion=i;j.expressInstall=k?k:false;H[H.length]=j;X(l,false)},getObjectById:function(l){var i=null;if(a.w3cdom&&S){var j=c(l);if(j){var k=j.getElementsByTagName(P)[0];if(!k||(k&&typeof j.SetVariable!=Z)){i=j}else{if(typeof k.SetVariable!=Z){i=k}}}}return i},embedSWF:function(n,u,r,t,j,m,k,p,s){if(!a.w3cdom||!n||!u||!r||!t||!j){return }r+="";t+="";if(O(j)){X(u,false);var q=(typeof s==P)?s:{};q.data=n;q.width=r;q.height=t;var o=(typeof p==P)?p:{};if(typeof k==P){for(var l in k){if(k[l]!=Object.prototype[l]){if(typeof o.flashvars!=Z){o.flashvars+="&"+l+"="+k[l]}else{o.flashvars=l+"="+k[l]}}}}J(function(){R(q,o,u);if(q.id==u){X(u,true)}})}else{if(m&&!C&&O("6.0.65")&&(a.win||a.mac)){X(u,false);J(function(){var i={};i.id=i.altContentId=u;i.width=r;i.height=t;i.expressInstall=m;D(i)})}}},getFlashPlayerVersion:function(){return{major:a.pv[0],minor:a.pv[1],release:a.pv[2]}},hasFlashPlayerVersion:O,createSWF:function(k,j,i){if(a.w3cdom&&S){return R(k,j,i)}else{return undefined}},createCSS:function(j,i){if(a.w3cdom){A(j,i)}},addDomLoadEvent:J,addLoadEvent:M,getQueryParamValue:function(m){var l=g.location.search||g.location.hash;if(m==null){return l}if(l){var k=l.substring(1).split("&");for(var j=0;j<k.length;j++){if(k[j].substring(0,k[j].indexOf("="))==m){return k[j].substring((k[j].indexOf("=")+1))}}}return""},expressInstallCallback:function(){if(C&&L){var i=c(K);if(i){i.parentNode.replaceChild(L,i);if(T){X(T,true);if(a.ie&&a.win){L.style.display="block"}}L=null;T=null;C=false}}}}}();

/*	sIFR 2.0.1
	Copyright 2004 - 2005 Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben

	This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
*/

var hasFlash=function(){var a=6;if(navigator.appVersion.indexOf("MSIE")!=-1&&navigator.appVersion.indexOf("Windows")>-1){document.write('<script language="VBScript"\> \non error resume next \nhasFlash = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash." & '+a+'))) \n</script\> \n');if(window.hasFlash!=null)return window.hasFlash}if(navigator.mimeTypes&&navigator.mimeTypes["application/x-shockwave-flash"]&&navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){var b=(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description;return parseInt(b.charAt(b.indexOf(".")-1))>=a}return false}();String.prototype.normalize=function(){return this.replace(/\s+/g," ")};if(Array.prototype.push==null){Array.prototype.push=function(){var i=0,a=this.length,b=arguments.length;while(i<b){this[a++]=arguments[i++]}return this.length}}if(!Function.prototype.apply){Function.prototype.apply=function(a,b){var c=[];var d,e;if(!a)a=window;if(!b)b=[];for(var i=0;i<b.length;i++){c[i]="b["+i+"]"}e="a.__applyTemp__("+c.join(",")+");";a.__applyTemp__=this;d=eval(e);a.__applyTemp__=null;return d}}function named(a){return new named.Arguments(a)}named.Arguments=function(a){this.oArgs=a};named.Arguments.prototype.constructor=named.Arguments;named.extract=function(a,b){var c,d;var i=a.length;while(i--){d=a[i];if(d!=null&&d.constructor!=null&&d.constructor==named.Arguments){c=a[i].oArgs;break}}if(c==null)return;for(e in c)if(b[e]!=null)b[e](c[e]);return};var parseSelector=function(){var a=/^([^#.>`]*)(#|\.|\>|\`)(.+)$/;function r(s,t){var u=s.split(/\s*\,\s*/);var v=[];for(var i=0;i<u.length;i++)v=v.concat(b(u[i],t));return v}function b(c,d,e){c=c.normalize().replace(" ","`");var f=c.match(a);var g,h,i,j,k,n;var l=[];if(f==null)f=[c,c];if(f[1]=="")f[1]="*";if(e==null)e="`";if(d==null)d=document;switch(f[2]){case "#":k=f[3].match(a);if(k==null)k=[null,f[3]];g=document.getElementById(k[1]);if(g==null||(f[1]!="*"&&!o(g,f[1])))return l;if(k.length==2){l.push(g);return l}return b(k[3],g,k[2]);case ".":if(e!=">")h=m(d,f[1]);else h=d.childNodes;for(i=0,n=h.length;i<n;i++){g=h[i];if(g.nodeType!=1)continue;k=f[3].match(a);if(k!=null){if(g.className==null||g.className.match("\\b"+k[1]+"\\b")==null)continue;j=b(k[3],g,k[2]);l=l.concat(j)}else if(g.className!=null&&g.className.match("\\b"+f[3]+"\\b")!=null)l.push(g)}return l;case ">":if(e!=">")h=m(d,f[1]);else h=d.childNodes;for(i=0,n=h.length;i<n;i++){g=h[i];if(g.nodeType!=1)continue;if(!o(g,f[1]))continue;j=b(f[3],g,">");l=l.concat(j)}return l;case "`":h=m(d,f[1]);for(i=0,n=h.length;i<n;i++){g=h[i];j=b(f[3],g,"`");l=l.concat(j)}return l;default:if(e!=">")h=m(d,f[1]);else h=d.childNodes;for(i=0,n=h.length;i<n;i++){g=h[i];if(g.nodeType!=1)continue;if(!o(g,f[1]))continue;l.push(g)}return l}}function m(d,o){if(o=="*"&&d.all!=null)return d.all;return d.getElementsByTagName(o)}function o(p,q){return q=="*"?true:p.nodeName.toLowerCase().replace("html:", "")==q.toLowerCase()}return r}();var sIFR=function(){var a="http://www.w3.org/1999/xhtml";var b=false;var c=false;var d;var ah=[];var al=document;var ak=al.documentElement;var am=window;var au=al.addEventListener;var av=am.addEventListener;var f=function(){var g=navigator.userAgent.toLowerCase();var f={a:g.indexOf("applewebkit")>-1,b:g.indexOf("safari")>-1,c:navigator.product!=null&&navigator.product.toLowerCase().indexOf("konqueror")>-1,d:g.indexOf("opera")>-1,e:al.contentType!=null&&al.contentType.indexOf("xml")>-1,f:true,g:true,h:null,i:null,j:null,k:null};f.l=f.a||f.c;f.m=!f.a&&navigator.product!=null&&navigator.product.toLowerCase()=="gecko";if(f.m)f.j=new Number(g.match(/.*gecko\/(\d{8}).*/)[1]);f.n=g.indexOf("msie")>-1&&!f.d&&!f.l&&!f.m;f.o=f.n&&g.match(/.*mac.*/)!=null;if(f.d)f.i=new Number(g.match(/.*opera(\s|\/)(\d+\.\d+)/)[2]);if(f.n||(f.d&&f.i<7.6))f.g=false;if(f.a)f.k=new Number(g.match(/.*applewebkit\/(\d+).*/)[1]);if(am.hasFlash&&(!f.n||f.o)){var aj=(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description;f.h=parseInt(aj.charAt(aj.indexOf(".")-1))}if(g.match(/.*(windows|mac).*/)==null||f.o||f.c||(f.d&&(g.match(/.*mac.*/)!=null||f.i<7.6))||(f.b&&f.h<7)||(!f.b&&f.a&&f.k<124)||(f.m&&f.j<20020523))f.f=false;if(!f.o&&!f.m&&al.createElementNS)try{al.createElementNS(a,"i").innerHTML=""}catch(e){f.e=true}f.p=f.c||(f.a&&f.k<312)||f.n;return f}();function at(){return{bIsWebKit:f.a,bIsSafari:f.b,bIsKonq:f.c,bIsOpera:f.d,bIsXML:f.e,bHasTransparencySupport:f.f,bUseDOM:f.g,nFlashVersion:f.h,nOperaVersion:f.i,nGeckoBuildDate:f.j,nWebKitVersion:f.k,bIsKHTML:f.l,bIsGecko:f.m,bIsIE:f.n,bIsIEMac:f.o,bUseInnerHTMLHack:f.p}}if(am.hasFlash==false||!al.getElementsByTagName||!al.getElementById||(f.e&&f.p))return{UA:at()};function af(e){if((!k.bAutoInit&&(am.event||e)!=null)||!l(e))return;b=true;for(var i=0,h=ah.length;i<h;i++)j.apply(null,ah[i]);ah=[]}var k=af;function l(e){if(c==false||k.bIsDisabled==true||((f.e&&f.m||f.l)&&e==null&&b==false)||(al.body==null||al.getElementsByTagName("body").length==0))return false;return true}function m(n){if(f.n)return n.replace(new RegExp("%\d{0}","g"),"%25");return n.replace(new RegExp("%(?!\d)","g"),"%25")}function as(p,q){return q=="*"?true:p.nodeName.toLowerCase().replace("html:", "")==q.toLowerCase()}function o(p,q,r,s,t){var u="";var v=p.firstChild;var w,x,y,z;if(s==null)s=0;if(t==null)t="";while(v){if(v.nodeType==3){z=v.nodeValue.replace("<","&lt;");switch(r){case "lower":u+=z.toLowerCase();break;case "upper":u+=z.toUpperCase();break;default:u+=z}}else if(v.nodeType==1){if(as(v,"a")&&!v.getAttribute("href")==false){if(v.getAttribute("target"))t+="&sifr_url_"+s+"_target="+v.getAttribute("target");t+="&sifr_url_"+s+"="+m(v.getAttribute("href")).replace(/&/g,"%26");u+='<a href="asfunction:_root.launchURL,'+s+'">';s++}else if(as(v,"br"))u+="<br/>";if(v.hasChildNodes()){y=o(v,null,r,s,t);u+=y.u;s=y.s;t=y.t}if(as(v,"a"))u+="</a>"}w=v;v=v.nextSibling;if(q!=null){x=w.parentNode.removeChild(w);q.appendChild(x)}}return{"u":u,"s":s,"t":t}}function A(B){if(al.createElementNS&&f.g)return al.createElementNS(a,B);return al.createElement(B)}function C(D,E,z){var p=A("param");p.setAttribute("name",E);p.setAttribute("value",z);D.appendChild(p)}function F(p,G){var H=p.className;if(H==null)H=G;else H=H.normalize()+(H==""?"":" ")+G;p.className=H}function aq(ar){var a=ak;if(k.bHideBrowserText==false)a=al.getElementsByTagName("body")[0];if((k.bHideBrowserText==false||ar)&&a)if(a.className==null||a.className.match(/\bsIFR\-hasFlash\b/)==null)F(a, "sIFR-hasFlash")}function j(I,J,K,L,M,N,O,P,Q,R,S,r,T){if(!l())return ah.push(arguments);aq();named.extract(arguments,{sSelector:function(ap){I=ap},sFlashSrc:function(ap){J=ap},sColor:function(ap){K=ap},sLinkColor:function(ap){L=ap},sHoverColor:function(ap){M=ap},sBgColor:function(ap){N=ap},nPaddingTop:function(ap){O=ap},nPaddingRight:function(ap){P=ap},nPaddingBottom:function(ap){Q=ap},nPaddingLeft:function(ap){R=ap},sFlashVars:function(ap){S=ap},sCase:function(ap){r=ap},sWmode:function(ap){T=ap}});var U=parseSelector(I);if(U.length==0)return false;if(S!=null)S="&"+S.normalize();else S="";if(K!=null)S+="&textcolor="+K;if(M!=null)S+="&hovercolor="+M;if(M!=null||L!=null)S+="&linkcolor="+(L||K);if(O==null)O=0;if(P==null)P=0;if(Q==null)Q=0;if(R==null)R=0;if(N==null)N="#FFFFFF";if(T=="transparent")if(!f.f)T="opaque";else N="transparent";if(T==null)T="";var p,V,W,X,Y,Z,aa,ab,ac;var ad=null;for(var i=0,h=U.length;i<h;i++){p=U[i];if(p.className!=null&&p.className.match(/\bsIFR\-replaced\b/)!=null)continue;V=p.offsetWidth-R-P;W=p.offsetHeight-O-Q;aa=A("span");aa.className="sIFR-alternate";ac=o(p,aa,r);Z="txt="+m(ac.u).replace(/\+/g,"%2B").replace(/&/g,"%26").replace(/\"/g, "%22").normalize() + S + "&w=" + V + "&h=" + W + ac.t;F(p,"sIFR-replaced");if(ad==null||!f.g){if(!f.g)p.innerHTML=['<embed class="sIFR-flash" type="application/x-shockwave-flash" src="',J,'" quality="best" wmode="',T,'" bgcolor="',N,'" flashvars="',Z,'" width="',V,'" height="',W,'" sifr="true"></embed>'].join("");else{if(f.d){ab=A("object");ab.setAttribute("data",J);C(ab,"quality","best");C(ab,"wmode",T);C(ab,"bgcolor",N)}else{ab=A("embed");ab.setAttribute("src",J);ab.setAttribute("quality","best");ab.setAttribute("flashvars",Z);ab.setAttribute("wmode",T);ab.setAttribute("bgcolor",N)}ab.setAttribute("sifr","true");ab.setAttribute("type","application/x-shockwave-flash");ab.className="sIFR-flash";if(!f.l||!f.e)ad=ab.cloneNode(true)}}else ab=ad.cloneNode(true);if(f.g){if(f.d)C(ab,"flashvars",Z);else ab.setAttribute("flashvars",Z);ab.setAttribute("width",V);ab.setAttribute("height",W);ab.style.width=V+"px";ab.style.height=W+"px";p.appendChild(ab)}p.appendChild(aa);if(f.p)p.innerHTML+=""}if(f.n&&k.bFixFragIdBug)setTimeout(function(){al.title=d},0)}function ai(){d=al.title}function ae(){if(k.bIsDisabled==true)return;c=true;if(k.bHideBrowserText)aq(true);if(am.attachEvent)am.attachEvent("onload",af);else if(!f.c&&(al.addEventListener||am.addEventListener)){if(f.a&&f.k>=132&&am.addEventListener)am.addEventListener("load",function(){setTimeout("sIFR({})",1)},false);else{if(al.addEventListener)al.addEventListener("load",af,false);if(am.addEventListener)am.addEventListener("load",af,false)}}else if(typeof am.onload=="function"){var ag=am.onload;am.onload=function(){ag();af()}}else am.onload=af;if(!f.n||am.location.hash=="")k.bFixFragIdBug=false;else ai()}k.UA=at();k.bAutoInit=true;k.bFixFragIdBug=true;k.replaceElement=j;k.updateDocumentTitle=ai;k.appendToClassName=F;k.setup=ae;k.debug=function(){aq(true)};k.debug.replaceNow=function(){ae();k()};k.bIsDisabled=false;k.bHideBrowserText=true;return k}();

if(typeof sIFR == "function" && !sIFR.UA.bIsIEMac){
	sIFR.setup();
};

/*	sIFR 2.0.1 Official Add-ons 1.2
	Copyright 2005 Mark Wubben

	This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
*/

if(typeof sIFR=="function")(function(){var j=document;var h=j.documentElement;sIFR.removeDecoyClasses=function(){function a(b){if(b&&b.className!=null)b.className=b.className.replace(/\bsIFR-hasFlash\b/,"")}return function(){a(h);a(j.getElementsByTagName("body")[0])}}();sIFR.preferenceManager={storage:{sCookieId:"sifr",set:function(a){var b=new Date();b.setFullYear(b.getFullYear()+3);j.cookie=[this.sCookieId,"=",a,";expires=",b.toGMTString(),";path=/"].join("")},get:function(){var a=j.cookie.match(new RegExp(";?"+this.sCookieId+"=([^;]+);?"));if(a!=null&&a[1]=="false")return false;else return true},reset:function(){var a=new Date();a.setFullYear(a.getFullYear()-1);j.cookie=[this.sCookieId,"=true;expires=",a.toGMTString(),";path=/"].join("")}},disable:function(){this.storage.set(false)},enable:function(){this.storage.set(true)},test:function(){return this.storage.get()}};if(sIFR.preferenceManager.test()==false){sIFR.bIsDisabled=true;sIFR.removeDecoyClasses()}sIFR.rollback=function(){function a(b){var c,d,e,f,g,h;var l=parseSelector(b);var i=l.length-1;var m=false;while(i>=0){c=l[i];l.length--;d=c.parentNode;if(c.getAttribute("sifr")=="true"){h=0;while(h<d.childNodes.length){c=d.childNodes[h];if(c.className=="sIFR-alternate"){e=c;h++;continue}d.removeChild(c)}if(e!=null){f=e.firstChild;while(f!=null){g=f.nextSibling;d.appendChild(e.removeChild(f));f=g}d.removeChild(e)}if(!sIFR.UA.bIsXML&&sIFR.UA.bUseInnerHTMLHack)d.innerHTML+="";d.className=d.className.replace(/\bsIFR\-replaced\b/,"")};m=true;i--}return m}return function(k){named.extract(arguments,{sSelector:function(a){k=a}});if(k==null)k="";else k+=">";sIFR.removeDecoyClasses();sIFR.bHideBrowserText=false;if(a(k+"embed")==false)a(k+"object")}}()})()

_global = this;

//Firebugx.js - makes all console calls ignored on non Firebug-enabled browsers
if (!window.console || !console.firebug)
{
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {}
}


//only proceed if we have MooTools
if(typeof(Class) == "function")
{
	window.addEvent('domready',function(){

		// Center on error notice if exists
		var ErrorNotification = document.getElementById('ErrorNotification');
		if(ErrorNotification) {
			window.location.href = window.location.href + '#ErrorNotification';
		}

		toolTipElements = $$('.toolTipElement');
		if(toolTipElements.length != 0)
		{
			var myTips = new Tips(toolTipElements, {
				timeOut: 700,
				maxTitleChars: 50, //I like my captions a little long
				maxOpacity: .9 // let's leave a little transparancy in there
			});
		}

		theHash = window.location.hash.split("&")[0].split("#")[1]
		//console.log(theHash)

		$$('.cropThis').each(function(el){
			console.log("cropThis for " + el);
		});

		InternalMessagesTableThs = $$('.InternalMessagesTable th')
		if(InternalMessagesTableThs.length != 0)
		{
			//select none/all links
			selectControls = new Element('th')
				.setHTML('')

			selectAll = new Element('a')
				.setHTML('All')
				.addEvent('click',function(){
					$$('.InternalMessagesTable input[type=checkbox]').each(function(el){
						//console.log(el);
						el.checked = true;
					});
				})
				.setStyle('cursor','pointer')
				.injectInside(selectControls)

			selectControls.appendText('/');

			selectNone = new Element('a')
				.setHTML('None')
				.addEvent('click',function(){
					$$('.InternalMessagesTable input[type=checkbox]').each(function(el){
						//console.log(el);
						el.checked = false;
					});
				})
				.setStyle('cursor','pointer')
				.injectInside(selectControls)

			$$('.InternalMessagesTable th').each(function(el){
				if(el.innerHTML == 'x')
					el.replaceWith(selectControls);
			});
		}

		//new text limit
		$$('.makeLimitTrigger').each(function(el) {
			params = el.getProperty('rel').split('|');
			makeLimit(params[0],params[1]);
		})
	});

	// Naomi took this out because it broke IE8
	//new Asset.images(['../images/loader.gif'])[0];

	String.extend({
		toQueryObject: function(){
			var o = {};
			$A(this.replace(/(^.*\?)|(#.*$)/g,'').split('&')).each(function(p){
				p = p.split("=");
				o[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
			});
			return o;
		}
	});

	window.location.querystring = window.location.href.toQueryObject();

	Element.extend({
		getLength: function(){
			len = this.value.length;
			id = this.id;
			$(this.id + '_charCur').innerHTML = len;
			$(this.id +'_length_input').setProperty('value',len);

			if(len > this.textLim && !this.isOver)
			{
				this.isOver = true;
				$(this.id + '_charLim').addClass('charLimOver');
			}

			if(len <= this.textLim && this.isOver)
			{
				this.isOver = false;
				$(this.id + '_charLim').removeClass('charLimOver');
			}
		}
	});

}

function submitIndicators(){
	$$('input[type=submit]').each(function(el) {
		if(el.value == 'Go')
			return;
		//console.log(el.value);
		//alert ("form");
		el.addEvent("click",function(e) {
			new Element('img')
					.setProperty('src','../images/loader.gif')
					.setStyles('margin:3px 0 0 5px;')
					.injectAfter(el);

			el.setStyles("background:#eee;color:#999;");
		});
	});
}


function makeLimit(id,lim)
{
	console.log($(id+"_jsLimDiv"));
	//$(id+"_jsLimDiv").setStyle("display","none");

	new Element("br")
		.injectInside($(id).getParent());

	$(id+"_charCur").setStyle('display','inline');
	$(id+"_charLimPost").innerHTML = "&nbsp;out of " + $(id+"_charLimPost").innerHTML;

	/*
	bigSpan = new Element("span")
		.setProperty("id",id+"_charLim")
		.addClass("charLim")
		.setHTML('<span id="'+id+'_charCur" class="charCur">0</span>/'+lim+' characters')
		.injectInside($(id).getParent());
	new Element("input")
		.setProperty("type","hidden")
		.setProperty("name",id+'_length')
		.setProperty("id",id+'_length_input')
		.injectInside($(id).getParent());
	*/

	//$(id).getParent().innerHTML += '<input type="hidden" name="'+id+'_length" id="'+id+'_length_input" />';
	$(id).textLim = lim;
	$(id).isOver = false;
	$(id).addEvent('keydown',$(id).getLength);
	$(id).addEvent('keyup',$(id).getLength);
	$(id).addEvent('keypress',$(id).getLength);
	$(id).getLength();

	len = $(id).value.length;
	$(id + '_charCur').innerHTML = len;
//	$(id).onkeydown = $(id).onkeyup = getLength(id,lim);
}


function addPaginationHash()
{
	if(getHash())
		$$('#businessListings .Pagination a').each(function(el){
			el.href = el.href + '#' + getHash();
			//console.log(el.href);
		})

}

function addPaginationRemote()
{
	$$('#businessListings .Pagination a').each(function(el){
		el.href = el.href + "&remote=1";
	})
}

//if we're in firefox, scroll the window using a session variable (cookie)
/*
if(window.gecko)
{
	var clearPreviousScrollCookie = false;
	window.addEvent('domready',function() {
		console.log("pre a click");
		$$('a').addEvent('click',function(){
			clearPreviousScrollCookie = true;
			Cookie.set('refresh_scroll_prev_url','');
			Cookie.set('refresh_scroll_prev_pos','');
		});
		console.log("post a click");
	});
	window.addEvent('unload',function(){
		//if we've just refreshed the page, don't bother resetting the previous page
		if(window.location != Cookie.get('refresh_scroll_url') && !clearPreviousScrollCookie)
		{
			Cookie.set('refresh_scroll_prev_url',Cookie.get('refresh_scroll_url'));
			Cookie.set('refresh_scroll_prev_pos',Cookie.get('refresh_scroll_pos'));
		}
		Cookie.set('refresh_scroll_url',window.location);
		Cookie.set('refresh_scroll_pos',window.getScrollTop());
	})

	window.addEvent('domready',function(){
		console.log("Cookie.get('refresh_scroll_url') is " + Cookie.get('refresh_scroll_url'));
		console.log("Cookie.get('refresh_scroll_pos') is " + Cookie.get('refresh_scroll_pos'));
		console.log("Cookie.get('refresh_scroll_prev_url') is " + Cookie.get('refresh_scroll_prev_url'));
		console.log("Cookie.get('refresh_scroll_prev_pos') is " + Cookie.get('refresh_scroll_prev_pos'));

		if(Cookie.get('refresh_scroll_url') == window.location)
			var myFx = new Fx.Scroll(window,{duration:0}).scrollTo(0,Cookie.get('refresh_scroll_pos')*1);
		else if(Cookie.get('refresh_scroll_prev_url') == window.location)
			var myFx = new Fx.Scroll(window,{duration:0}).scrollTo(0,Cookie.get('refresh_scroll_prev_pos')*1);
	})
}
*/
function debug(value)
{
	newValue = '';
	for(i=0;i < value.length;i++)
	{
		if(value.charCodeAt(i) == 10)
			newValue += "<br>";
		else
			newValue += value.charAt(i);
	}

	if(typeof(debugElm)=="undefined")
		debugElm = new Element('div')
			.setStyles({
				'position': 'absolute',
				'padding': '30px',
				'background': '#FFC',
				'top': '0',
				'left': '0',
				'width': 'auto',
				'text-align': 'left'
			})

	debugElm.setHTML(debugElm.innerHTML + newValue);
	debugElm.injectInside($$('body')[0]);
}


function getHash()
{
	return window.location.hash.split('#')[1];
}



function IEContentLoaded (w, fn) {
	var d = w.document, done = false,
	// only fire once
	init = function () {
		if (!done) {
			done = true;
			fn();
		}
	};
	// polling for no errors
	(function () {
		try {
			// throws errors until after ondocumentready
			d.documentElement.doScroll('left');
		} catch (e) {
			setTimeout(arguments.callee, 50);
			return;
		}
		// no errors, fire
		init();
	})();
	// trying to always fire before onload
	d.onreadystatechange = function() {
		if (d.readyState == 'complete') {
			d.onreadystatechange = null;
			init();
		}
	};
}

function eventShowMoreLessToggle(id,e) {
	$('event_short_'+id).toggleClass('invisible');
	$('event_long_'+id).toggleClass('invisible');

	if($('event_long_'+id).hasClass('invisible')) {
		window.location.hash = 'event_anchor_'+id;
	}
}

function hideNotification(noticeid){
	var sid = $$('input[name=sid]') ? $$('input[name=sid]')[0].value : '';
	var phpsessid = $$('input[name=PHPSESSID]') ? $$('input[name=PHPSESSID]')[0].value : '';

	var ajax = new Ajax('/index.php?close_note_ajax=true&close_note='+noticeid+'&sid='+ sid +'&PHPSESSID='+phpsessid,{});
	ajax.request();

	$('notification_'+noticeid).style.display = 'none';

	return false;
}

function hideNotifications(){
	var sid = $$('input[name=sid]') ? $$('input[name=sid]')[0].value : '';
	var phpsessid = $$('input[name=PHPSESSID]') ? $$('input[name=PHPSESSID]')[0].value : '';

	var ajax = new Ajax('/index.php?close_note_ajax=true&close_all_notes=true&sid='+ sid+'&PHPSESSID='+phpsessid,{});
	ajax.request();

	$('notifications_multiple').style.display = 'none';

	return false;
}



//
var last_toggler_clicked;
var accordionScroller = new Fx.Scroll(window);

function accordion_open_start(el)
{
  last_toggler_clicked = el;
  console.log(el.getPosition().y + "ASDASD");
}

function accordion_open_finished()
{
  if(!last_toggler_clicked)
    return;
  
  console.log("ASDA");
  
  ltc_y = last_toggler_clicked.getPosition().y;
  win_y = window.getScrollTop();
  
  if(ltc_y < win_y)
  {
    //document.documentElement.scrollTop = ltc_y;
    accordionScroller.toElement(last_toggler_clicked);
  } 
  last_toggler_clicked = false;
//  console.log();
//  console.log(window.pageYOffset);
}


window.addEvent('domready',function(){
	//if we don't have a directory on which to operate
	if(!$('directory'))
		return;

	//chrome bug
	window.addEvent('load',function() {
		$('midcol').setStyle('position','relative');
	});
		
	//classified section purple links
	$$('#directory[rel=classified] a').each(function(el){
		str = el.getProperty('href');

		if(!str)
			return;
		arr = str.split('#');

		if(arr.length <= 1)
			return;

		linkHash = arr[1];

		if((linkHash != theHash && el.getProperty('rel') != theHash) || !theHash)
			return

		//if(el.getProperty('rel'))
			//return;


		itr = el;
		i = 0;
		while(itr.getTag() != 'div')
		{
			//console.log(itr);
			if(itr.getTag() == 'a')
				itr.setStyle('color','#990066');
			testPrevious = itr.getPrevious();
			if(testPrevious)
				itr = itr.getPrevious();
			else
				itr = itr.getParent();
			i++;
		}

		//if(linkHash == theHash || el.getProperty('rel') == theHash)
			//el.setStyle('color','#990066');
	});


	//making the business section
	$$('#directory[rel=business] a').each(function(el){
		//console.log("business dir a's " + el.getProperty('href'));
		//if(typeof(el.getProperty))
			//return;
		el = $(el);
		if(el.getAttribute('href') == '')
			return;

		str = window.location + "";
		output = '';
		if(str.charAt(7) == "b")
		{
			for(i in el)
				output += el[i] + " => " + i;
			//alert(output);
		}

		hashArr = el.getAttribute('href').split('#');
		linkHash = hashArr[1];
		theHash = window.location.hash.split("&")[0].split("#")[1];

		testStr = el.getAttribute('rel');
		//q always tests false for the regexp
		if(!$defined(testStr) || testStr == '')
			testStr = 'q';
		else
			el.addEvent('click',function(){
				$$('#directory[rel=business] a').setStyle('color','#3F94E4');


				//set the ancestors of the element to red
				itr = this;
				i = 0;
				while(itr.getTag() != 'div')
				{
					//console.log(itr);
					if(itr.getTag() == 'a');
						itr.setStyle('color','#990066');
					testPrevious = itr.getPrevious();
					if(testPrevious)
						itr = itr.getPrevious();
					else
						itr = itr.getParent();
					i++;
				}
			});


		//testing in ie
		//$('midcol').innerHTML += 'theHash: ' + theHash + '; rel: ' + testStr + 'linkHash==thehash: ' + (linkHash==theHash) + "<br>";

		//console.log("el.innerHTML.substr(0,6) IS " + el.innerHTML.substr(0,7));

		if($defined(theHash) && (theHash.test(testStr) || linkHash == theHash) && el.innerHTML.substr(0,7) != "see all")
			$(el).setStyle('color','#990066');
		else
			$(el).setStyle('color','#3F94E4');

		if(el.innerHTML.substr(0,7) == "see all" && !window.location.querystring.noSubCats && !window.location.querystring.remote && linkHash == theHash)
			$(el).setStyle('color','#990066');


	});

	//set cat hashes
	$$('.showcase a').each(function(el){
		el.setProperty('href',el.getProperty('href') + '&catHash=' + theHash);
	})




	//display business listings on click
	if($('businessListings'))
	{
		lowerLimitQS = ''

		//get the lower limit if it exists
		if($('lower_limit_key'))
			lowerLimitQS = '&' + $('lower_limit_key').value + '=' + $('lower_limit_val').value;

		$$('#directory a').each(function(el) {

			//only parent categories have a rel attribute
			if(!el.rel)
				return;
			//get the cat_id from the rel tag of the accordion menu
			//it's in the last three numbers of the rel tag
			el.cat_id = el.rel.substr(el.rel.length-3,3)*1;


			el.ajax = new Ajax('index.php?action=dynamic_business_dir&noSubCats=1&sid='+ $('sid').value + '&PHPSESSID=' + $('PHPSESSID').value + lowerLimitQS,{
				postBody:"qs_cat_id="+ el.cat_id + "&region_id=" + $('region_id').value,
				onComplete:function(response){
					$('businessListings').innerHTML = response;

					$$('.showcase a').each(function(innerEl){
						innerEl.setProperty('href',innerEl.getProperty('href') + '&catHash=' + el.rel);
					})
					addPaginationRemote();
					addPaginationHash();
				},
				onFailure:function(instance){
					$('businessListings').innerHTML = '<p style="padding:10px">Sorry, an error has occured.</p>';
				},
				onRequest:function(instance){
					$('businessListings').innerHTML='<p style="padding:10px"><img src="images/loader.gif" style="float:left;margin-right:10px"/> Fetching listings for ' + el.innerHTML + '</p>';
				}
			});



			//el.ajax = new Ajax('index.php');

			el.addEvent('click',function() {
				this.ajax.request();
			})
		});
	}

	//load the section on a page refresh unless we're in a paginated set
	var dirLinks = $$('a[rel=' + getHash() + ']');
	//console.log("!window.location.querystring.restore_state_manually IS " + !window.location.querystring.restore_state_manually)
	//console.log("!window.location.querystring.qs_cat_id IS " + !window.location.querystring.qs_cat_id)
	//console.log("dirLinks.length IS " + dirLinks.length);
	if($('businessListings') && getHash() && !window.location.querystring.restore_state_manually && !window.location.querystring.qs_cat_id && dirLinks.length > 0)
		if(!window.location.querystring.restore_state_alt || (window.location.querystring.restore_state_alt && window.location.querystring.remote))
			dirLinks[0].ajax.request();

	//put the hash in all pagination links
	addPaginationHash();

});

/*
	Slimbox v1.3 - The ultimate lightweight Lightbox clone
	by Christophe Beyls (http://www.digitalia.be) - MIT-style license.
	Inspired by the original Lightbox v2 by Lokesh Dhakar.
*/

var Lightbox = {

	init: function(options){
		this.options = Object.extend({
			resizeDuration: 200,
			resizeTransition: Fx.Transitions.sineInOut,
			initialWidth: 250,
			initialHeight: 250,
			animateCaption: false,
			container: document.body,
			showControls: false,
			showNumbers: true,
			descriptions: false,
			opacity: 0.7,
			minWidth: 400,
			maxCaptionHeight:200
		}, options || {});

		this.anchors = [];
		$each(document.links, function(el){
			if (el.rel && el.rel.test(/^lightbox/i)){
				el.onclick = this.click.pass(el, this);
				this.anchors.push(el);
			}
		}, this);
		this.eventKeyDown = this.keyboardListener.bindAsEventListener(this);
		this.eventPosition = this.position.bind(this);

		this.overlay = new Element('div').setProperty('id', 'lbOverlay').injectInside(this.options.container);

		this.center = new Element('div').setProperty('id', 'lbCenter').setStyles({width: this.options.initialWidth+'px', height: this.options.initialHeight+'px', marginLeft: '-'+(this.options.initialWidth/2)+'px', display: 'none'}).injectInside(this.options.container);
		this.image = new Element('div').setProperty('id', 'lbImage').injectInside(this.center);
		
		this.bottomContainer = new Element('div').setProperty('id', 'lbBottomContainer').setStyle('display', 'none').injectInside(this.options.container);
		this.bottom = new Element('div').setProperty('id', 'lbBottom').injectInside(this.bottomContainer);
		
		if(this.options.showControls){
			this.controlDiv = new Element('div').setProperty('id','lbControls').injectInside(this.bottom);
		}else{
			this.controlDiv = this.image;
		}
		this.prevLink = new Element('a').setProperties({id: 'lbPrevLink', href: '#'}).setStyle('display', 'none').injectInside(this.controlDiv);
		this.nextLink = this.prevLink.clone().setProperty('id', 'lbNextLink').injectInside(this.controlDiv);
		this.prevLink.onclick = this.previous.bind(this);
		this.nextLink.onclick = this.next.bind(this);

		this.closeButton = new Element('a').setProperties({id: 'lbCloseLink', href: '#'}).injectInside(this.bottom)
		this.closeButton.onclick = this.overlay.onclick = this.close.bind(this);
		
		this.caption = new Element('div').setProperty('id', 'lbCaption').injectInside(this.bottom);
		if(this.options.descriptions != false){
			this.options.descriptions = $$(this.options.descriptions);
			this.description = new Element('div').setProperty('id', 'lbDescription').injectInside(this.bottom);
		}
		if(this.options.showNumbers){
			this.number = new Element('div').setProperty('id', 'lbNumber').injectInside(this.bottom);
		}
		new Element('div').setStyle('clear', 'both').injectInside(this.bottom);

		var nextEffect = this.nextEffect.bind(this);
		this.fx = {
			overlay: this.overlay.effect('opacity', {duration: 500}).hide(),
			resize: this.center.effects({duration: this.options.resizeDuration, transition: this.options.resizeTransition, onComplete: nextEffect}),
			image: this.image.effect('opacity', {duration: 500, onComplete: nextEffect}),
			bottom: this.bottom.effect('margin-top', {duration: 400, onComplete: nextEffect})
		};

		this.preloadPrev = new Image();
		this.preloadNext = new Image();
	},

	click: function(link){
		if (link.rel.length == 8) return this.show(link.href, link.title);

		var j, imageNum, images = [];
		this.anchors.each(function(el){
			if (el.rel == link.rel){
				for (j = 0; j < images.length; j++) if(images[j][0] == el.href) break;
				if (j == images.length){
					images.push([el.href, el.title]);
					if (el.href == link.href) imageNum = j;
				}
			}
		}, this);
		return this.open(images, imageNum);
	},

	show: function(url, title){
		return this.open([[url, title]], 0);
	},

	open: function(images, imageNum){
		this.images = images;
		this.position();
		this.setup(true);
		this.top = window.getScrollTop() + (window.getHeight() / 15);
		this.center.setStyles({top: this.top+'px', display: ''});
		this.fx.overlay.start(this.options.opacity);
		return this.changeImage(imageNum);
	},

	position: function(){
		//this.overlay.setStyles({top: window.getScrollTop()+'px', height: window.getHeight()+'px'});
		if(this.options.container == document.body){
			var h = window.getScrollHeight()+'px';
		}else{
			var h = this.options.container.getStyle('height');
		}
		this.overlay.setStyles({top: '0px', height: h});
	},

	setup: function(open){
		var elements = $A(document.getElementsByTagName('object'));
		if (window.ie) elements.extend(document.getElementsByTagName('select'));
		elements.each(function(el){ el.style.visibility = open ? 'hidden' : ''; });
		var fn = open ? 'addEvent' : 'removeEvent';
		window[fn]('scroll', this.eventPosition)[fn]('resize', this.eventPosition);
		document[fn]('keydown', this.eventKeyDown);
		this.step = 0;
	},

	keyboardListener: function(event){
		switch (event.keyCode){
			case 27: case 88: case 67: this.close(); break;
			case 37: case 80: this.previous(); break;	
			case 39: case 78: this.next();
		}
	},

	previous: function(){
		return this.changeImage(this.activeImage-1);
	},

	next: function(){
		return this.changeImage(this.activeImage+1);
	},

	changeImage: function(imageNum){
		if (this.step || (imageNum < 0) || (imageNum >= this.images.length)) return false;
		this.step = 1;
		this.activeImage = imageNum;
		this.bottomContainer.style.display = this.prevLink.style.display = this.nextLink.style.display = 'none';
		this.fx.image.hide();
		this.center.className = 'lbLoading';

		this.preload = new Image();
		this.preload.onload = this.nextEffect.bind(this);
		this.preload.src = this.images[imageNum][0];
		return false;
	},

	nextEffect: function(){
		switch (this.step++){
		case 1:
			this.center.className = '';
			this.image.style.backgroundImage = 'url('+this.images[this.activeImage][0]+')';
			this.image.style.width =  this.preload.width+'px';
			this.bottom.style.width = this.bottomContainer.style.width;
			//this.image.style.height = this.prevLink.style.height = this.nextLink.style.height = this.preload.height+'px';
			if(this.options.showControls){
				this.image.style.height = this.preload.height+'px';
			}else{
				this.image.style.height = this.prevLink.style.height = this.nextLink.style.height = this.preload.height+'px';
			}

			this.caption.setHTML(this.images[this.activeImage][1] || '');
			if(this.options.descriptions != false){
				if(this.description.getFirst()){this.description.getFirst().remove()};
				var cl = this.options.descriptions[this.activeImage].clone();
				cl.setStyle('display', 'block').injectInside(this.description);
			}
			if(this.options.showNumbers){
				this.number.setHTML((this.images.length == 1) ? '' : 'Image '+(this.activeImage+1)+' of '+this.images.length);
			}

			if (this.activeImage) this.preloadPrev.src = this.images[this.activeImage-1][0];
			if (this.activeImage != (this.images.length - 1)) this.preloadNext.src = this.images[this.activeImage+1][0];
			if (this.center.clientHeight != this.image.offsetHeight){
				this.fx.resize.start({height: this.image.offsetHeight});
				break;
			}
			this.step++;
		case 2:
			if (this.center.clientWidth != this.image.offsetWidth){
				newWidth = this.image.offsetWidth;
				this.fx.resize.start({width: newWidth, marginLeft: -newWidth/2});
				break;
			}
			this.step++;
		case 3:
			scrollOffset = 30;
			newWidth = this.image.offsetWidth;

			this.caption.setStyles({width:(newWidth-scrollOffset)+'px'});
			
			this.bottomContainer.setStyles({top: (this.top + this.center.clientHeight)+'px', height: '0px', marginLeft: this.center.style.marginLeft, display: '', width: newWidth+'px'});
			this.bottom.setStyles({width: newWidth+'px'});
			this.fx.image.start(1);
			//var extra = this.closeButton.getStyle('height').toInt();

			captionHeight = this.caption.getSize().size.y;
			console.log(captionHeight);
			if(captionHeight > this.options.maxCaptionHeight)
				captionHeight = this.options.maxCaptionHeight;
			
			//this.caption.setStyle("height",captionHeight+"px");
			this.caption.setStyle("display","none");
			

			var extra = captionHeight;
			if(this.options.descriptions != false){extra += this.description.getStyle('height').toInt()}
			if(this.options.showControls){extra += this.controlDiv.getStyle('height').toInt()}
			if(this.options.showNumbers){extra += this.number.getStyle('height').toInt()}
			
			this.closeButton.setStyle('marginTop', 0);
			if(this.activeImage != 0) this.prevLink.style.display = '';
			if(this.activeImage != (this.images.length - 1)) this.nextLink.style.display = '';

			this.bottom.setStyles({width: (newWidth-20) + 'px'});
			

			
			break;
		case 4:
			if (this.options.animateCaption){
				this.fx.bottom.set(-this.bottom.offsetHeight);
				this.bottomContainer.style.height = '';
				this.fx.bottom.start(0);
				break;
			}
			this.bottomContainer.style.height = '';
		case 5:

			//if (this.activeImage) this.prevLink.style.display = '';
			//if (this.activeImage != (this.images.length - 1)) this.nextLink.style.display = '';
			this.step = 0;
			break;
		}
	},

	close: function(){
		if (this.step < 0) return;
		this.step = -1;
		if (this.preload){
			this.preload.onload = Class.empty;
			this.preload = null;
		}
		for (var f in this.fx) this.fx[f].stop();
		this.center.style.display = this.bottomContainer.style.display = 'none';
		this.fx.overlay.chain(this.setup.pass(false, this)).start(0);
		return false;
	}
};








if(window.ie)
	window.addEvent('load',function(){Lightbox.init({showControls: true, resizeDuration: 150});});
else
	window.addEvent('domready',function(){Lightbox.init({showControls: true, resizeDuration: 150});});

//window.addEvent('domready',function(){Lightbox.init({showControls: true, resizeDuration: 150});});

/* Flash Detect code taken from http://www.featureblend.com/javascript-flash-detection-library.html
http://www.featureblend.com/license.txt
*/
var FlashDetect=new function(){var self=this;self.installed=false;self.raw="";self.major=-1;self.minor=-1;self.revision=-1;self.revisionStr="";var activeXDetectRules=[{"name":"ShockwaveFlash.ShockwaveFlash.7","version":function(obj){return getActiveXVersion(obj);}},{"name":"ShockwaveFlash.ShockwaveFlash.6","version":function(obj){var version="6,0,21";try{obj.AllowScriptAccess="always";version=getActiveXVersion(obj);}catch(err){}
return version;}},{"name":"ShockwaveFlash.ShockwaveFlash","version":function(obj){return getActiveXVersion(obj);}}];var getActiveXVersion=function(activeXObj){var version=-1;try{version=activeXObj.GetVariable("$version");}catch(err){}
return version;};var getActiveXObject=function(name){var obj=-1;try{obj=new ActiveXObject(name);}catch(err){}
return obj;};var parseActiveXVersion=function(str){var versionArray=str.split(",");return{"raw":str,"major":parseInt(versionArray[0].split(" ")[1],10),"minor":parseInt(versionArray[1],10),"revision":parseInt(versionArray[2],10),"revisionStr":versionArray[2]};};var parseStandardVersion=function(str){var descParts=str.split(/ +/);var majorMinor=descParts[2].split(/\./);var revisionStr=descParts[3];return{"raw":str,"major":parseInt(majorMinor[0],10),"minor":parseInt(majorMinor[1],10),"revisionStr":revisionStr,"revision":parseRevisionStrToInt(revisionStr)};};var parseRevisionStrToInt=function(str){return parseInt(str.replace(/[a-zA-Z]/g,""),10)||self.revision;};self.majorAtLeast=function(version){return self.major>=version;};self.FlashDetect=function(){if(navigator.plugins&&navigator.plugins.length>0){var type='application/x-shockwave-flash';var mimeTypes=navigator.mimeTypes;if(mimeTypes&&mimeTypes[type]&&mimeTypes[type].enabledPlugin&&mimeTypes[type].enabledPlugin.description){var version=mimeTypes[type].enabledPlugin.description;var versionObj=parseStandardVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revisionStr=versionObj.revisionStr;self.revision=versionObj.revision;self.installed=true;}}else if(navigator.appVersion.indexOf("Mac")==-1&&window.execScript){var version=-1;for(var i=0;i<activeXDetectRules.length&&version==-1;i++){var obj=getActiveXObject(activeXDetectRules[i].name);if(typeof obj=="object"){self.installed=true;version=activeXDetectRules[i].version(obj);if(version!=-1){var versionObj=parseActiveXVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revision=versionObj.revision;self.revisionStr=versionObj.revisionStr;}}}}}();};FlashDetect.release="1.0.3";

/**
 * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
 *
 * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/,  http://www.vinterwebb.se/
 *
 * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */

/* ******************* */
/* Constructor & Init  */
/* ******************* */
var SWFUpload;

if (SWFUpload == undefined) {
	SWFUpload = function (settings) {
		this.initSWFUpload(settings);
	};
}

SWFUpload.prototype.initSWFUpload = function (settings) {
	try {
		this.customSettings = {};	// A container where developers can place their own settings associated with this instance.
		this.settings = settings;
		this.eventQueue = [];
		this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
		this.movieElement = null;

		// Setup global control tracking
		SWFUpload.instances[this.movieName] = this;

		// Load the settings.  Load the Flash movie.
		this.initSettings();
		this.loadFlash();
		this.displayDebugInfo();
	} catch (ex) {
		delete SWFUpload.instances[this.movieName];
		throw ex;
	}
};

/* *************** */
/* Static Members  */
/* *************** */
SWFUpload.instances = {};
SWFUpload.movieCount = 0;
SWFUpload.version = "2.2.0 Beta 2";
SWFUpload.QUEUE_ERROR = {
	QUEUE_LIMIT_EXCEEDED	  		: -100,
	FILE_EXCEEDS_SIZE_LIMIT  		: -110,
	ZERO_BYTE_FILE			  		: -120,
	INVALID_FILETYPE		  		: -130
};
SWFUpload.UPLOAD_ERROR = {
	HTTP_ERROR				  		: -200,
	MISSING_UPLOAD_URL	      		: -210,
	IO_ERROR				  		: -220,
	SECURITY_ERROR			  		: -230,
	UPLOAD_LIMIT_EXCEEDED	  		: -240,
	UPLOAD_FAILED			  		: -250,
	SPECIFIED_FILE_ID_NOT_FOUND		: -260,
	FILE_VALIDATION_FAILED	  		: -270,
	FILE_CANCELLED			  		: -280,
	UPLOAD_STOPPED					: -290
};
SWFUpload.FILE_STATUS = {
	QUEUED		 : -1,
	IN_PROGRESS	 : -2,
	ERROR		 : -3,
	COMPLETE	 : -4,
	CANCELLED	 : -5
};
SWFUpload.BUTTON_ACTION = {
	SELECT_FILE  : -100,
	SELECT_FILES : -110,
	START_UPLOAD : -120
};
SWFUpload.CURSOR = {
	ARROW : -1,
	HAND : -2
};
SWFUpload.WINDOW_MODE = {
	WINDOW : "window",
	TRANSPARENT : "transparent",
	OPAQUE : "opaque"
};

/* ******************** */
/* Instance Members  */
/* ******************** */

// Private: initSettings ensures that all the
// settings are set, getting a default value if one was not assigned.
SWFUpload.prototype.initSettings = function () {
	this.ensureDefault = function (settingName, defaultValue) {
		this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
	};

	// Upload backend settings
	this.ensureDefault("upload_url", "");
	this.ensureDefault("file_post_name", "Filedata");
	this.ensureDefault("post_params", {});
	this.ensureDefault("use_query_string", false);
	this.ensureDefault("requeue_on_error", false);
	this.ensureDefault("http_success", []);

	// File Settings
	this.ensureDefault("file_types", "*.*");
	this.ensureDefault("file_types_description", "All Files");
	this.ensureDefault("file_size_limit", 0);	// Default zero means "unlimited"
	this.ensureDefault("file_upload_limit", 0);
	this.ensureDefault("file_queue_limit", 0);

	// Flash Settings
	this.ensureDefault("flash_url", "swfupload.swf");
	this.ensureDefault("prevent_swf_caching", true);

	// Button Settings
	this.ensureDefault("button_image_url", "");
	this.ensureDefault("button_width", 1);
	this.ensureDefault("button_height", 1);
	this.ensureDefault("button_text", "");
	this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
	this.ensureDefault("button_text_top_padding", 0);
	this.ensureDefault("button_text_left_padding", 0);
	this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
	this.ensureDefault("button_disabled", false);
	this.ensureDefault("button_placeholder_id", null);
	this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
	this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);

	// Debug Settings
	this.ensureDefault("debug", false);
	this.settings.debug_enabled = this.settings.debug;	// Here to maintain v2 API

	// Event Handlers
	this.settings.return_upload_start_handler = this.returnUploadStart;
	this.ensureDefault("swfupload_loaded_handler", null);
	this.ensureDefault("file_dialog_start_handler", null);
	this.ensureDefault("file_queued_handler", null);
	this.ensureDefault("file_queue_error_handler", null);
	this.ensureDefault("file_dialog_complete_handler", null);

	this.ensureDefault("upload_start_handler", null);
	this.ensureDefault("upload_progress_handler", null);
	this.ensureDefault("upload_error_handler", null);
	this.ensureDefault("upload_success_handler", null);
	this.ensureDefault("upload_complete_handler", null);

	this.ensureDefault("debug_handler", this.debugMessage);

	this.ensureDefault("custom_settings", {});

	// Other settings
	this.customSettings = this.settings.custom_settings;

	// Update the flash url if needed
	if (this.settings.prevent_swf_caching) {
		this.settings.flash_url = this.settings.flash_url + "?swfuploadrnd=" + Math.floor(Math.random() * 999999999);
	}

	delete this.ensureDefault;
};

SWFUpload.prototype.loadFlash = function () {
	if (this.settings.button_placeholder_id !== "") {
		this.replaceWithFlash();
	} else {
		this.appendFlash();
	}
};

// Private: appendFlash gets the HTML tag for the Flash
// It then appends the flash to the body
SWFUpload.prototype.appendFlash = function () {
	var targetElement, container;

	// Make sure an element with the ID we are going to use doesn't already exist
	if (document.getElementById(this.movieName) !== null) {
		throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
	}

	// Get the body tag where we will be adding the flash movie
	targetElement = document.getElementsByTagName("body")[0];

	if (targetElement == undefined) {
		throw "Could not find the 'body' element.";
	}

	// Append the container and load the flash
	container = document.createElement("div");
	container.style.width = "1px";
	container.style.height = "1px";
	container.style.overflow = "hidden";

	targetElement.appendChild(container);
	container.innerHTML = this.getFlashHTML();	// Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
};

// Private: replaceWithFlash replaces the button_placeholder element with the flash movie.
SWFUpload.prototype.replaceWithFlash = function () {
	var targetElement, tempParent;

	// Make sure an element with the ID we are going to use doesn't already exist
	if (document.getElementById(this.movieName) !== null) {
		throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
	}

	// Get the element where we will be placing the flash movie
	targetElement = document.getElementById(this.settings.button_placeholder_id);

	if (targetElement == undefined) {
		throw "Could not find the placeholder element.";
	}

	// Append the container and load the flash
	tempParent = document.createElement("div");
	tempParent.innerHTML = this.getFlashHTML();	// Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
	targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);

};

// Private: getFlashHTML generates the object tag needed to embed the flash in to the document
SWFUpload.prototype.getFlashHTML = function () {
	// Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
	return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
				'<param name="wmode" value="', this.settings.button_window_mode , '" />',
				'<param name="movie" value="', this.settings.flash_url, '" />',
				'<param name="quality" value="high" />',
				'<param name="menu" value="false" />',
				'<param name="allowScriptAccess" value="always" />',
				'<param name="flashvars" value="' + this.getFlashVars() + '" />',
				'</object>'].join("");
};

// Private: getFlashVars builds the parameter string that will be passed
// to flash in the flashvars param.
SWFUpload.prototype.getFlashVars = function () {
	// Build a string from the post param object
	var paramString = this.buildParamString();
	var httpSuccessString = this.settings.http_success.join(",");

	// Build the parameter string
	return ["movieName=", encodeURIComponent(this.movieName),
			"&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
			"&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
			"&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
			"&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
			"&amp;params=", encodeURIComponent(paramString),
			"&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
			"&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
			"&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
			"&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
			"&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
			"&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
			"&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
			"&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
			"&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
			"&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
			"&amp;buttonText=", encodeURIComponent(this.settings.button_text),
			"&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
			"&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
			"&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
			"&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
			"&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
			"&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
		].join("");
};

// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload
// The element is cached after the first lookup
SWFUpload.prototype.getMovieElement = function () {
	if (this.movieElement == undefined) {
		this.movieElement = document.getElementById(this.movieName);
	}

	if (this.movieElement === null) {
		throw "Could not find Flash element";
	}

	return this.movieElement;
};

// Private: buildParamString takes the name/value pairs in the post_params setting object
// and joins them up in to a string formatted "name=value&amp;name=value"
SWFUpload.prototype.buildParamString = function () {
	var postParams = this.settings.post_params;
	var paramStringPairs = [];

	if (typeof(postParams) === "object") {
		for (var name in postParams) {
			if (postParams.hasOwnProperty(name)) {
				paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
			}
		}
	}

	return paramStringPairs.join("&amp;");
};

// Public: Used to remove a SWFUpload instance from the page. This method strives to remove
// all references to the SWF, and other objects so memory is properly freed.
// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
SWFUpload.prototype.destroy = function () {
	try {
		// Make sure Flash is done before we try to remove it
		this.stopUpload();

		// Remove the SWFUpload DOM nodes
		var movieElement = null;
		try {
			movieElement = this.getMovieElement();
		} catch (ex) {
		}

		if (movieElement != undefined && movieElement.parentNode != undefined && typeof movieElement.parentNode.removeChild === "function") {
			var container = movieElement.parentNode;
			if (container != undefined) {
				container.removeChild(movieElement);
				if (container.parentNode != undefined && typeof container.parentNode.removeChild === "function") {
					container.parentNode.removeChild(container);
				}
			}
		}

		// Destroy references
		SWFUpload.instances[this.movieName] = null;
		delete SWFUpload.instances[this.movieName];

		delete this.movieElement;
		delete this.settings;
		delete this.customSettings;
		delete this.eventQueue;
		delete this.movieName;

		delete window[this.movieName];

		return true;
	} catch (ex1) {
		return false;
	}
};

// Public: displayDebugInfo prints out settings and configuration
// information about this SWFUpload instance.
// This function (and any references to it) can be deleted when placing
// SWFUpload in production.
SWFUpload.prototype.displayDebugInfo = function () {
	this.debug(
		[
			"---SWFUpload Instance Info---\n",
			"Version: ", SWFUpload.version, "\n",
			"Movie Name: ", this.movieName, "\n",
			"Settings:\n",
			"\t", "upload_url:               ", this.settings.upload_url, "\n",
			"\t", "flash_url:                ", this.settings.flash_url, "\n",
			"\t", "use_query_string:         ", this.settings.use_query_string.toString(), "\n",
			"\t", "requeue_on_error:         ", this.settings.requeue_on_error.toString(), "\n",
			"\t", "http_success:             ", this.settings.http_success.join(", "), "\n",
			"\t", "file_post_name:           ", this.settings.file_post_name, "\n",
			"\t", "post_params:              ", this.settings.post_params.toString(), "\n",
			"\t", "file_types:               ", this.settings.file_types, "\n",
			"\t", "file_types_description:   ", this.settings.file_types_description, "\n",
			"\t", "file_size_limit:          ", this.settings.file_size_limit, "\n",
			"\t", "file_upload_limit:        ", this.settings.file_upload_limit, "\n",
			"\t", "file_queue_limit:         ", this.settings.file_queue_limit, "\n",
			"\t", "debug:                    ", this.settings.debug.toString(), "\n",

			"\t", "prevent_swf_caching:      ", this.settings.prevent_swf_caching.toString(), "\n",

			"\t", "button_placeholder_id:    ", this.settings.button_placeholder_id.toString(), "\n",
			"\t", "button_image_url:         ", this.settings.button_image_url.toString(), "\n",
			"\t", "button_width:             ", this.settings.button_width.toString(), "\n",
			"\t", "button_height:            ", this.settings.button_height.toString(), "\n",
			"\t", "button_text:              ", this.settings.button_text.toString(), "\n",
			"\t", "button_text_style:        ", this.settings.button_text_style.toString(), "\n",
			"\t", "button_text_top_padding:  ", this.settings.button_text_top_padding.toString(), "\n",
			"\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
			"\t", "button_action:            ", this.settings.button_action.toString(), "\n",
			"\t", "button_disabled:          ", this.settings.button_disabled.toString(), "\n",

			"\t", "custom_settings:          ", this.settings.custom_settings.toString(), "\n",
			"Event Handlers:\n",
			"\t", "swfupload_loaded_handler assigned:  ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
			"\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
			"\t", "file_queued_handler assigned:       ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
			"\t", "file_queue_error_handler assigned:  ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
			"\t", "upload_start_handler assigned:      ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
			"\t", "upload_progress_handler assigned:   ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
			"\t", "upload_error_handler assigned:      ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
			"\t", "upload_success_handler assigned:    ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
			"\t", "upload_complete_handler assigned:   ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
			"\t", "debug_handler assigned:             ", (typeof this.settings.debug_handler === "function").toString(), "\n"
		].join("")
	);
};

/* Note: addSetting and getSetting are no longer used by SWFUpload but are included
	the maintain v2 API compatibility
*/
// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
SWFUpload.prototype.addSetting = function (name, value, default_value) {
    if (value == undefined) {
        return (this.settings[name] = default_value);
    } else {
        return (this.settings[name] = value);
	}
};

// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
SWFUpload.prototype.getSetting = function (name) {
    if (this.settings[name] != undefined) {
        return this.settings[name];
	}

    return "";
};



// Private: callFlash handles function calls made to the Flash element.
// Calls are made with a setTimeout for some functions to work around
// bugs in the ExternalInterface library.
SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
	argumentArray = argumentArray || [];

	var movieElement = this.getMovieElement();
	var returnValue;

	if (typeof movieElement[functionName] === "function") {
		// We have to go through all this if/else stuff because the Flash functions don't have apply() and only accept the exact number of arguments.
		if (argumentArray.length === 0) {
			returnValue = movieElement[functionName]();
		} else if (argumentArray.length === 1) {
			returnValue = movieElement[functionName](argumentArray[0]);
		} else if (argumentArray.length === 2) {
			returnValue = movieElement[functionName](argumentArray[0], argumentArray[1]);
		} else if (argumentArray.length === 3) {
			returnValue = movieElement[functionName](argumentArray[0], argumentArray[1], argumentArray[2]);
		} else {
			throw "Too many arguments";
		}

		// Unescape file post param values
		if (returnValue != undefined && typeof returnValue.post === "object") {
			returnValue = this.unescapeFilePostParams(returnValue);
		}

		return returnValue;
	} else {
		throw "Invalid function name: " + functionName;
	}
};


/* *****************************
	-- Flash control methods --
	Your UI should use these
	to operate SWFUpload
   ***************************** */

// Public: selectFile causes a File Selection Dialog window to appear.  This
// dialog only allows 1 file to be selected. WARNING: this function does not work in Flash Player 10
SWFUpload.prototype.selectFile = function () {
	this.callFlash("SelectFile");
};

// Public: selectFiles causes a File Selection Dialog window to appear/ This
// dialog allows the user to select any number of files
// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
// If the selection name length is too long the dialog will fail in an unpredictable manner.  There is no work-around
// for this bug.  WARNING: this function does not work in Flash Player 10
SWFUpload.prototype.selectFiles = function () {
	this.callFlash("SelectFiles");
};


// Public: startUpload starts uploading the first file in the queue unless
// the optional parameter 'fileID' specifies the ID
SWFUpload.prototype.startUpload = function (fileID) {
	this.callFlash("StartUpload", [fileID]);
};

// Public: cancelUpload cancels any queued file.  The fileID parameter may be the file ID or index.
// If you do not specify a fileID the current uploading file or first file in the queue is cancelled.
// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.
SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {
	if (triggerErrorEvent !== false) {
		triggerErrorEvent = true;
	}
	this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
};

// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
// If nothing is currently uploading then nothing happens.
SWFUpload.prototype.stopUpload = function () {
	this.callFlash("StopUpload");
};

/* ************************
 * Settings methods
 *   These methods change the SWFUpload settings.
 *   SWFUpload settings should not be changed directly on the settings object
 *   since many of the settings need to be passed to Flash in order to take
 *   effect.
 * *********************** */

// Public: getStats gets the file statistics object.
SWFUpload.prototype.getStats = function () {
	return this.callFlash("GetStats");
};

// Public: setStats changes the SWFUpload statistics.  You shouldn't need to
// change the statistics but you can.  Changing the statistics does not
// affect SWFUpload accept for the successful_uploads count which is used
// by the upload_limit setting to determine how many files the user may upload.
SWFUpload.prototype.setStats = function (statsObject) {
	this.callFlash("SetStats", [statsObject]);
};

// Public: getFile retrieves a File object by ID or Index.  If the file is
// not found then 'null' is returned.
SWFUpload.prototype.getFile = function (fileID) {
	if (typeof(fileID) === "number") {
		return this.callFlash("GetFileByIndex", [fileID]);
	} else {
		return this.callFlash("GetFile", [fileID]);
	}
};

// Public: addFileParam sets a name/value pair that will be posted with the
// file specified by the Files ID.  If the name already exists then the
// exiting value will be overwritten.
SWFUpload.prototype.addFileParam = function (fileID, name, value) {
	return this.callFlash("AddFileParam", [fileID, name, value]);
};

// Public: removeFileParam removes a previously set (by addFileParam) name/value
// pair from the specified file.
SWFUpload.prototype.removeFileParam = function (fileID, name) {
	this.callFlash("RemoveFileParam", [fileID, name]);
};

// Public: setUploadUrl changes the upload_url setting.
SWFUpload.prototype.setUploadURL = function (url) {
	this.settings.upload_url = url.toString();
	this.callFlash("SetUploadURL", [url]);
};

// Public: setPostParams changes the post_params setting
SWFUpload.prototype.setPostParams = function (paramsObject) {
	this.settings.post_params = paramsObject;
	this.callFlash("SetPostParams", [paramsObject]);
};

// Public: addPostParam adds post name/value pair.  Each name can have only one value.
SWFUpload.prototype.addPostParam = function (name, value) {
	this.settings.post_params[name] = value;
	this.callFlash("SetPostParams", [this.settings.post_params]);
};

// Public: removePostParam deletes post name/value pair.
SWFUpload.prototype.removePostParam = function (name) {
	delete this.settings.post_params[name];
	this.callFlash("SetPostParams", [this.settings.post_params]);
};

// Public: setFileTypes changes the file_types setting and the file_types_description setting
SWFUpload.prototype.setFileTypes = function (types, description) {
	this.settings.file_types = types;
	this.settings.file_types_description = description;
	this.callFlash("SetFileTypes", [types, description]);
};

// Public: setFileSizeLimit changes the file_size_limit setting
SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {
	this.settings.file_size_limit = fileSizeLimit;
	this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
};

// Public: setFileUploadLimit changes the file_upload_limit setting
SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {
	this.settings.file_upload_limit = fileUploadLimit;
	this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
};

// Public: setFileQueueLimit changes the file_queue_limit setting
SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {
	this.settings.file_queue_limit = fileQueueLimit;
	this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
};

// Public: setFilePostName changes the file_post_name setting
SWFUpload.prototype.setFilePostName = function (filePostName) {
	this.settings.file_post_name = filePostName;
	this.callFlash("SetFilePostName", [filePostName]);
};

// Public: setUseQueryString changes the use_query_string setting
SWFUpload.prototype.setUseQueryString = function (useQueryString) {
	this.settings.use_query_string = useQueryString;
	this.callFlash("SetUseQueryString", [useQueryString]);
};

// Public: setRequeueOnError changes the requeue_on_error setting
SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {
	this.settings.requeue_on_error = requeueOnError;
	this.callFlash("SetRequeueOnError", [requeueOnError]);
};

// Public: setHTTPSuccess changes the http_success setting
SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
	if (typeof http_status_codes === "string") {
		http_status_codes = http_status_codes.replace(" ", "").split(",");
	}

	this.settings.http_success = http_status_codes;
	this.callFlash("SetHTTPSuccess", [http_status_codes]);
};


// Public: setDebugEnabled changes the debug_enabled setting
SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
	this.settings.debug_enabled = debugEnabled;
	this.callFlash("SetDebugEnabled", [debugEnabled]);
};

// Public: setButtonImageURL loads a button image sprite
SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {
	if (buttonImageURL == undefined) {
		buttonImageURL = "";
	}

	this.settings.button_image_url = buttonImageURL;
	this.callFlash("SetButtonImageURL", [buttonImageURL]);
};

// Public: setButtonDimensions resizes the Flash Movie and button
SWFUpload.prototype.setButtonDimensions = function (width, height) {
	this.settings.button_width = width;
	this.settings.button_height = height;

	var movie = this.getMovieElement();
	if (movie != undefined) {
		movie.style.width = width + "px";
		movie.style.height = height + "px";
	}

	this.callFlash("SetButtonDimensions", [width, height]);
};
// Public: setButtonText Changes the text overlaid on the button
SWFUpload.prototype.setButtonText = function (html) {
	this.settings.button_text = html;
	this.callFlash("SetButtonText", [html]);
};
// Public: setButtonTextPadding changes the top and left padding of the text overlay
SWFUpload.prototype.setButtonTextPadding = function (left, top) {
	this.settings.button_text_top_padding = top;
	this.settings.button_text_left_padding = left;
	this.callFlash("SetButtonTextPadding", [left, top]);
};

// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
SWFUpload.prototype.setButtonTextStyle = function (css) {
	this.settings.button_text_style = css;
	this.callFlash("SetButtonTextStyle", [css]);
};
// Public: setButtonDisabled disables/enables the button
SWFUpload.prototype.setButtonDisabled = function (isDisabled) {
	this.settings.button_disabled = isDisabled;
	this.callFlash("SetButtonDisabled", [isDisabled]);
};
// Public: setButtonAction sets the action that occurs when the button is clicked
SWFUpload.prototype.setButtonAction = function (buttonAction) {
	this.settings.button_action = buttonAction;
	this.callFlash("SetButtonAction", [buttonAction]);
};

// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button
SWFUpload.prototype.setButtonCursor = function (cursor) {
	this.settings.button_cursor = cursor;
	this.callFlash("SetButtonCursor", [cursor]);
};

/* *******************************
	Flash Event Interfaces
	These functions are used by Flash to trigger the various
	events.

	All these functions a Private.

	Because the ExternalInterface library is buggy the event calls
	are added to a queue and the queue then executed by a setTimeout.
	This ensures that events are executed in a determinate order and that
	the ExternalInterface bugs are avoided.
******************************* */

SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {
	// Warning: Don't call this.debug inside here or you'll create an infinite loop

	if (argumentArray == undefined) {
		argumentArray = [];
	} else if (!(argumentArray instanceof Array)) {
		argumentArray = [argumentArray];
	}

	var self = this;
	if (typeof this.settings[handlerName] === "function") {
		// Queue the event
		this.eventQueue.push(function () {
			this.settings[handlerName].apply(this, argumentArray);
		});

		// Execute the next queued event
		setTimeout(function () {
			self.executeNextEvent();
		}, 0);

	} else if (this.settings[handlerName] !== null) {
		throw "Event handler " + handlerName + " is unknown or is not a function";
	}
};

// Private: Causes the next event in the queue to be executed.  Since events are queued using a setTimeout
// we must queue them in order to garentee that they are executed in order.
SWFUpload.prototype.executeNextEvent = function () {
	// Warning: Don't call this.debug inside here or you'll create an infinite loop

	var  f = this.eventQueue ? this.eventQueue.shift() : null;
	if (typeof(f) === "function") {
		f.apply(this);
	}
};

// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
// properties that contain characters that are not valid for JavaScript identifiers. To work around this
// the Flash Component escapes the parameter names and we must unescape again before passing them along.
SWFUpload.prototype.unescapeFilePostParams = function (file) {
	var reg = /[$]([0-9a-f]{4})/i;
	var unescapedPost = {};
	var uk;

	if (file != undefined) {
		for (var k in file.post) {
			if (file.post.hasOwnProperty(k)) {
				uk = k;
				var match;
				while ((match = reg.exec(uk)) !== null) {
					uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
				}
				unescapedPost[uk] = file.post[k];
			}
		}

		file.post = unescapedPost;
	}

	return file;
};

SWFUpload.prototype.flashReady = function () {
	// Check that the movie element is loaded correctly with its ExternalInterface methods defined
	var movieElement = this.getMovieElement();
	if (typeof movieElement.StartUpload !== "function") {
		throw "ExternalInterface methods failed to initialize.";
	}

	// Fix IE Flash/Form bug
	if (window[this.movieName] == undefined) {
		window[this.movieName] = movieElement;
	}

	this.queueEvent("swfupload_loaded_handler");
};


/* This is a chance to do something before the browse window opens */
SWFUpload.prototype.fileDialogStart = function () {
	this.queueEvent("file_dialog_start_handler");
};


/* Called when a file is successfully added to the queue. */
SWFUpload.prototype.fileQueued = function (file) {
	file = this.unescapeFilePostParams(file);
	this.queueEvent("file_queued_handler", file);
};


/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
	file = this.unescapeFilePostParams(file);
	this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
};

/* Called after the file dialog has closed and the selected files have been queued.
	You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued) {
	this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued]);
};

SWFUpload.prototype.uploadStart = function (file) {
	file = this.unescapeFilePostParams(file);
	this.debug("UPLOAD START!!!!");
	this.queueEvent("return_upload_start_handler", file);
};

SWFUpload.prototype.returnUploadStart = function (file) {
	var returnValue;
	if (typeof this.settings.upload_start_handler === "function") {
		file = this.unescapeFilePostParams(file);
		returnValue = this.settings.upload_start_handler.call(this, file);
	} else if (this.settings.upload_start_handler != undefined) {
		throw "upload_start_handler must be a function";
	}

	// Convert undefined to true so if nothing is returned from the upload_start_handler it is
	// interpretted as 'true'.
	if (returnValue === undefined) {
		returnValue = true;
	}

	returnValue = !!returnValue;

	this.callFlash("ReturnUploadStart", [returnValue]);
};



SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
	file = this.unescapeFilePostParams(file);
	this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
};

SWFUpload.prototype.uploadError = function (file, errorCode, message) {
	file = this.unescapeFilePostParams(file);
	this.debug(errorCode);
	this.debug(message);
	this.queueEvent("upload_error_handler", [file, errorCode, message]);
};

SWFUpload.prototype.uploadSuccess = function (file, serverData) {
	file = this.unescapeFilePostParams(file);
	this.debug("SWFUpload.prototype.uploadSuccess");
	this.debug(serverData);
	this.queueEvent("upload_success_handler", [file, serverData]);
};

SWFUpload.prototype.uploadComplete = function (file) {
	file = this.unescapeFilePostParams(file);
	this.queueEvent("upload_complete_handler", file);
};

/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
   internal debug console.  You can override this event and have messages written where you want. */
SWFUpload.prototype.debug = function (message) {
	this.queueEvent("debug_handler", message);
};


/* **********************************
	Debug Console
	The debug console is a self contained, in page location
	for debug message to be sent.  The Debug Console adds
	itself to the body if necessary.

	The console is automatically scrolled as messages appear.

	If you are using your own debug handler or when you deploy to production and
	have debug disabled you can remove these functions to reduce the file size
	and complexity.
********************************** */

// Private: debugMessage is the default debug_handler.  If you want to print debug messages
// call the debug() function.  When overriding the function your own function should
// check to see if the debug setting is true before outputting debug information.
SWFUpload.prototype.debugMessage = function (message) {
	if (this.settings.debug) {
		var exceptionMessage, exceptionValues = [];

		// Check for an exception object and print it nicely
		if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
			for (var key in message) {
				if (message.hasOwnProperty(key)) {
					exceptionValues.push(key + ": " + message[key]);
				}
			}
			exceptionMessage = exceptionValues.join("\n") || "";
			exceptionValues = exceptionMessage.split("\n");
			exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
			SWFUpload.Console.writeLine(exceptionMessage);
		} else {
			SWFUpload.Console.writeLine(message);
		}
	}
};

SWFUpload.Console = {};
SWFUpload.Console.writeLine = function (message) {
	var console, documentForm;

	try {
		console = document.getElementById("SWFUpload_Console");

		if (!console) {
			documentForm = document.createElement("form");
			document.getElementsByTagName("body")[0].appendChild(documentForm);

			console = document.createElement("textarea");
			console.id = "SWFUpload_Console";
			console.style.fontFamily = "monospace";
			console.setAttribute("wrap", "off");
			console.wrap = "off";
			console.style.overflow = "auto";
			console.style.width = "700px";
			console.style.height = "350px";
			console.style.margin = "5px";
			documentForm.appendChild(console);
		}

		console.value += message + "\n";

		console.scrollTop = console.scrollHeight - console.clientHeight;
	} catch (ex) {
		alert("Exception: " + ex.name + " Message: " + ex.message);
	}
};


/*
------------ START USER DEFINED HANDLERS-----------------------
*/

function fileQueueError(file, errorCode, message) {
	try {
		if (errorCode === SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED) {
			alert("You have attempted to queue too many files.\n" + (message === 0 ? "You have reached the upload limit." : "You may select " + (message > 1 ? "up to " + message + " files." : "one file.")));
			return;
		}

		var progress = this.customSettings.progress;
		progress.setError();
		progress.toggleCancel(false);

		switch (errorCode) {
		case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
			progress.setStatus("Filesize exceeds limit.");
			alert("Sorry, maximum file size is 2mb.  Please choose an image less than 2mb, or reduce the file size of your image with photo editing software.");
			this.debug("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
			progress.setStatus("Cannot upload Zero Byte files.");
			this.debug("Error Code: Zero byte file, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
			progress.setStatus("Invalid File Type.");
			this.debug("Error Code: Invalid File Type, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:
			alert("You have selected too many files.  " +  (message > 1 ? "You may only add " +  message + " more files" : "You cannot add any more files."));
			break;
		default:
			if (file !== null) {
				progress.setStatus("Unhandled Error");
			}
			this.debug("Error Code: " + errorCode + ", File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		}
	} catch (ex) {
        this.debug(ex);
    }
}


function fileDialogComplete(numFiles) {
	this.startUpload();
	try {
		this.startUpload();
	} catch (ex)  {
        this.debug(ex);
	}
}

function uploadFileCancelled(file, queuelength) {
	var li = document.getElementById(file.id);
	li.innerHTML = file.name + " - cancelled";
	li.className = "SWFUploadFileItem uploadCancelled";
	var queueinfo = document.getElementById("queueinfo");
	queueinfo.innerHTML = queuelength + " files queued";
}

function uploadStart(file, position, queuelength) {
	try {
		/* I don't want to do any file validation or anything,  I'll just update the UI and return true to indicate that the upload should start */
		this.customSettings.progress.setFile(file);
		this.customSettings.progress.setStatus("Uploading...");
		this.customSettings.progress.toggleCancel(true, this);
	}
	catch (ex) {
		this.debug(ex);
	}
}

function uploadProgress(file, bytesLoaded, bytesTotal) {
	var percent = Math.ceil((bytesLoaded / bytesTotal) * 100);

	this.customSettings.progress.setProgress(percent);

	if(percent >= 100)
	{
		this.customSettings.progress.setStatus('<img src="/_img/loader_eee.gif" style="float:left;display:block;margin-right:5px" /> Please wait...');
	}
	else
		this.customSettings.progress.setStatus("Uploading - " + Math.round(bytesLoaded/1024) + "kb / " + Math.round(bytesTotal/1024) + "kb");
}

function uploadError(file,errorCode, message) {
	try {
		var progress = this.customSettings.progress;
		progress.setError();
		progress.toggleCancel(false);

		switch (errorCode) {
		case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
			progress.setStatus("Upload Error: " + message);
			this.debug("Error Code: HTTP Error, File name: " + file.name + ", Message: " + message);
			break;
		case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
			progress.setStatus("Configuration Error");
			this.debug("Error Code: No backend file, File name: " + file.name + ", Message: " + message);
			break;
		case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
			progress.setStatus("Upload Failed.");
			this.debug("Error Code: Upload Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		case SWFUpload.UPLOAD_ERROR.IO_ERROR:
			progress.setStatus("Server (IO) Error");
			this.debug("Error Code: IO Error, File name: " + file.name + ", Message: " + message);
			break;
		case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
			progress.setStatus("Security Error");
			this.debug("Error Code: Security Error, File name: " + file.name + ", Message: " + message);
			break;
		case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
			progress.setStatus("Upload limit exceeded.");
			this.debug("Error Code: Upload Limit Exceeded, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
			progress.setStatus("File not found.");
			this.debug("Error Code: The file was not found, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
			progress.setStatus("Failed Validation.  Upload skipped.");
			this.debug("Error Code: File Validation Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
			progress.setStatus("Cancelled");
			progress.setCancelled();
			break;
		case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
			progress.setStatus("Stopped");
			break;
		default:
			progress.setStatus("Unhandled Error: " + errorCode);
			this.debug("Error Code: " + errorCode + ", File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
			break;
		}
	} catch (ex) {
        this.debug(ex);
    }
}

function uploadSuccess(file) {
	try {
		this.debug("uploadSuccess!!");
		this.customSettings.progress.setComplete();
		this.customSettings.progress.toggleCancel(false);

		//if we've got a rel on the image uploader div, put that in the status as well
		message = "Image Uploaded!";
		extraMessage = this.customSettings.extraUploadedText;
		if(extraMessage != null)
			message += "<br>" + extraMessage;

		this.customSettings.progress.setStatus(message);

	} catch (ex) {
		this.debug(ex);
	}

	//new Fx.Style($(file.id + "progress"), 'background-color', {duration:500}).start('#666', '#0a0');

	//get the new image from the server
	new Ajax('index.php?action=get_image&id=' + this.customSettings.imageId + '&type=' + this.customSettings.imageType + '&getImage=true',{
		onComplete : function(response){

			if(!response)
				return false;

			imageURLs = response.split("|");
			thumbURL = imageURLs[0];
			largeURL = imageURLs[1];

			refreshMsg = new Element("div")
				.setHTML('Refresh page to see image')
				.setStyles({'fontWeight':'normal','lineHeight':'0.8em'})
				.setProperty('class','refreshMsg');

			newImage = new Element("img")
				.setProperty('src',thumbURL)
				.setProperty('class','refreshMsg')

			if(this.customSettings.imageClass == "lightbox")
			{
				//create lightbox link
				theImage = new Element("a")
					.setProperty('target','_blank')
					.setProperty('rel','lightbox')
					.setProperty('href',largeURL)
				newImage
					.addClass("border")
					.addClass("swfu")
					.injectInside(theImage);
			}
			else
				theImage = newImage;

			var container = this.customSettings.imageContainer;
			var images = container.getElements('img')
			var children = container.getChildren();

			//get the requisite delete image message
			for(i=0;i<children.length;i++)
				{
					if($(children[i]).hasClass('deleteImageLink'))
					{
						deleteLink = $(children[i]);
						deleteLink.setStyle('display','inline');
					}
				}

			//if we're doing the "ad" section, do something different
			if(this.customSettings.imageClass == "ad")
			{
				if($('theImage'))
				{
					$('theImage').setProperty('src',imageURLs[0]);
				}
				else
				{
					$('theHeading').setHTML('Current Graphic')
					$('theTD').innerHTML = '<img src="' + imageURLs[0] + '" id="theImage" border=0>';
				}
			}
			//if we're updating a user's avatar
			else if(this.customSettings.imageClass == 'avatar')
			{
				if(images.length != 0)
				{
					images[0].setProperty('src',thumbURL);
					images[0].setStyle('display','block');
				}
				else
				{
					if(typeof(deleteLink) == "undefined")
						theImage.injectInside(container);
					else if(deleteLink.getPrevious().getTag() == 'br')
						theImage.injectBefore(deleteLink.getPrevious());
					else
						theImage.injectBefore(deleteLink);
				}
				//set the image_previously_updated field
				$('image_previously_updated').value = 1;
			}
			//otherwise do something normal
			else
			{
				if(images.length != 0)
				{
					var oldImage = images[0];
					if(oldImage.getParent().getTag() == "a") {
						oldImage = images[0].getParent()
					}
					spans = oldImage.getParent().getElements('span');
					if(spans.length > 0)
						oldImage.getParent().getElements('span')[0].setStyle("display","none");
					oldImage.replaceWith(theImage);
					oldImage.setStyle('display','block');
				}
				else
				{
					if(typeof(deleteLink) == "undefined")
						theImage.injectInside(container);
					else if(deleteLink.getPrevious().getTag() == 'br')
						theImage.injectBefore(deleteLink.getPrevious());
					else
						theImage.injectBefore(deleteLink);

				}
				Lightbox.init({showControls: true, resizeDuration: 150})
			}
		}.bind(this)
	}).request()
}

function uploadComplete(file) {
	try {
		/*  I want the next upload to continue automatically so I'll call startUpload here */
		if (this.getStats().files_queued != 0) {
			this.startUpload();
		}
	} catch (ex) {
		this.debug(ex);
	}
}

// uploader only support flash 9.28+, so just display old fashioned
// file browse button
if(FlashDetect.majorAtLeast(10) || (FlashDetect.majorAtLeast(9) && FlashDetect.revision >= 28)){
	if(window.ie)
		IEContentLoaded(window,initSWFUploaders);
	else
		window.addEvent('domready',initSWFUploaders);
}

function initSWFUploaders()
{
	itr = 0;

	$$('.imageUploader').each(function(el){
		id = el.getProperty("id");

		var idArr = id.split("__");
		var imageType = idArr[0];
		var imageId = idArr[1];
		var imageFieldName = idArr[2];
		var imageClass = idArr[3];

		var progress = new FileProgress(id);

		msg = '';
		msg += 'Uploader instance' + itr + '\n-------------\n';
		swfuOptions = {
			file_size_limit: "2048", //kB,
			file_types: "*.jpg;*.gif;*.png",
			file_types_description:  "*.jpg;*.gif;*.png",
			flash_url: "/swfup/Flash/swfupload.swf",
			file_queue_limit:1,

			button_image_url : "_img/invis_button.png",
			button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
			button_width : 90,
			button_height : 32,
			button_text : "<span class='btnText'>Browse</span><br/><span class='maxSize'>(max 2mb)</span>",
			button_text_style: '.btnText {text-align:center;font-size:12px;color:#990066;font-family:verdana,arial,helvetica,sans-serif;} .maxSize{text-align:center;font-size:10px;color:#666666;font-family:verdana,arial,helvetica,sans-serif;}',
			button_action : SWFUpload.BUTTON_ACTION.SELECT_FILES,
			button_disable : false,
			button_cursor : -2, //hand

			file_queue_error_handler : fileQueueError,
			file_dialog_complete_handler: fileDialogComplete,
			upload_start_handler : uploadStart,
			upload_progress_handler : uploadProgress,
			upload_error_handler : uploadError,
			upload_success_handler : uploadSuccess,
			upload_complete_handler: uploadComplete,



			prevent_swf_caching: true,

			custom_settings : {
					imageType:imageType,
					imageId:imageId,
					imageFieldName:imageFieldName,
					imageClass:imageClass,
					imageContainer:el.getParent().getParent().getFirst(),
					progress:progress,
					extraUploadedText:el.getProperty('rel')
			},

			debug : false
		}

		if(window.ie)
			swfuOptions.flash_url = "/swfup/Flash/swfupload.swf?x=" + Math.ceil(Math.random()*1000000);

		swfuOptions.upload_url = "/upload.php?type=" + imageType + "&id=" + imageId + "&fieldName=" + imageFieldName;
		idArr = id.split("__");

		swfuOptions.button_placeholder_id = el.getChildren()[0].id;

		//fix for tds with a width and colspan
		if(window.ie)
		{
			$$('td.FormDefinition').each(function(el){
				if(el.getProperty('colspan') == '2')
					el.setStyle('width','auto');
			})
		}

		if(itr==0)
		{
			swfuOptions.flash_loaded_callback = 'swfu_0.flashLoaded';
			swfu_0 = new SWFUpload(swfuOptions);
		}
		if(itr==1)
		{
			swfuOptions.flash_loaded_callback = 'swfu_1.flashLoaded';
			swfu_1 = new SWFUpload(swfuOptions);
		}
		if(itr==2)
		{
			swfuOptions.flash_loaded_callback = 'swfu_2.flashLoaded';
			swfu_2 = new SWFUpload(swfuOptions);
		}
		if(itr==3)
		{
			swfuOptions.flash_loaded_callback = 'swfu_3.flashLoaded';
			swfu_3 = new SWFUpload(swfuOptions);
		}
		if(itr==4)
		{
			swfuOptions.flash_loaded_callback = 'swfu_4.flashLoaded';
			swfu_4 = new SWFUpload(swfuOptions);
		}
		if(itr==5)
		{
			swfuOptions.flash_loaded_callback = 'swfu_5.flashLoaded';
			swfu_5 = new SWFUpload(swfuOptions);
		}

		itr++;
	});

	//make swfu delete links
	$$('.deleteImageLink').each(function(el){
		el.theHref = el.getProperty('href');
		el.setProperty('href','javascript:void(0);');
		el.addEvent('click',function(){
			this.confirmDelete.setStyle('display','block');
		})

		el.confirmDelete = new Element("div")
			.setHTML("Are you sure?<br/>")
			.setStyle('display','none')
			.addClass('confirmDelete')
			.injectInside(el.getParent())

		el.yes = new Element("a")
			.setHTML("Yes ")
			.injectInside(el.confirmDelete)


		el.yes.setProperty('href','javascript:void(0);')
			.injectInside(el.confirmDelete)
			.addEvent('click',function(){
				if(el.getProperty('rel') == 'avatar')
					$('image_previously_updated').value = 0;
				new Ajax(el.theHref,{
					onComplete:function(){

						// Hide "Delete Image" Link
						el.setStyle('display','none');

						// Hide "Are you sure" div
						el.yes.getParent().setStyle('display','none');

						el.getParent().getChildren().each(function(child){
							if((child.getTag() == 'a' && child.getChildren().length > 0) || child.getTag() == 'img')
								child.setStyle('display','none');
						});

						// Hide progress info
						var swfdiv = el.getParent().getParent().getChildren()[1].getChildren()[0];
						$$('#'+swfdiv.id+' .progressWrapper').setStyle('display','none');
					}
				}).request();
			});



		el.no = new Element("a")
			.setHTML("No")
			.setProperty('href','javascript:void(0);')
			.injectInside(el.confirmDelete)
			.addEvent("click",function(){
				this.getParent().setStyle('display','none');
			})
	});
}

// Constructor
// file is a SWFUpload file object
// targetID is the HTML element id attribute that the FileProgress HTML structure will be added to.
function FileProgress(targetID) {
	this.targetID = targetID;

	this.opacity = 100;
	this.height = 0;

	this.fileProgressWrapper = document.createElement("div");
	this.fileProgressWrapper.className = "progressWrapper";
	this.fileProgressWrapper.id = targetID+"_fileProgressWrapper";

	this.fileProgressElement = document.createElement("div");
	this.fileProgressElement.className = "progressContainer";

	this.progressCancel = document.createElement("a");
	this.progressCancel.className = "progressCancel";
	this.progressCancel.href = "#";
	this.progressCancel.innerHTML = "cancel";
	this.progressCancel.style.visibility = "hidden";

	this.progressText = document.createElement("div");
	this.progressText.className = "progressName";

	this.progressBar = document.createElement("div");
	this.progressBar.className = "progressBarInProgress";

	this.progressStatus = document.createElement("div");
	this.progressStatus.className = "progressBarStatus";
	this.progressStatus.innerHTML = "&nbsp;";

	//this.fileProgressElement.appendChild(this.progressCancel);
	this.fileProgressElement.appendChild(this.progressText);
	this.fileProgressElement.appendChild(this.progressBar);
	this.fileProgressElement.appendChild(this.progressStatus);

	this.fileProgressWrapper.appendChild(this.fileProgressElement);

	document.getElementById(targetID).appendChild(this.fileProgressWrapper);

	this.height = this.fileProgressWrapper.offsetHeight;
}

FileProgress.prototype.setFile = function (file) {
	this.fileID = file.id;

	this.progressText.innerHTML = file.name;

	this.progressBar.className = "progressBarInProgress";

	this.progressStatus.className = "progressBarStatus";
	this.progressStatus.innerHTML = "&nbsp;";

	this.fileProgressWrapper.setStyle('display','block');

}
FileProgress.prototype.setProgress = function (percentage) {
	this.progressStatus.className = "progressBarStatus";
	this.progressBar.className = "progressBarInProgress";
	this.progressBar.style.width = percentage + "%";
};
FileProgress.prototype.setComplete = function () {
	this.progressStatus.className = "progressBarStatus";
	this.progressBar.className = "progressBarComplete";
	this.progressBar.style.width = "";
};
FileProgress.prototype.setError = function () {
	this.progressStatus.className = "progressBarStatus progressBarStatusError";
	this.progressBar.className = "progressBarError";
	this.progressBar.style.width = "";
};
FileProgress.prototype.setCancelled = function () {
	this.progressStatus.className = "progressBarStatus";
	this.progressBar.className = "progressBarError";
	this.progressBar.style.width = "";
};
FileProgress.prototype.setStatus = function (status) {
	this.progressStatus.innerHTML = status;
};

// Show/Hide the cancel button
FileProgress.prototype.toggleCancel = function (show, swfUploadInstance) {
	// We aren't using the cancel button for now
	return;
	this.progressCancel.style.visibility = show ? "visible" : "hidden";
	if (swfUploadInstance) {
		this.progressCancel.onclick = function () {
			swfUploadInstance.cancelUpload(this.fileID);
			return false;
		};
	}
};


AnythingSearchManager = function() {
	this.base_search_cats = ['Marketplace','Classifieds','Articles','Community','Events'];
	this.more_search_cats = ['Users','Photos','Blog'];

	this.blueArrow = '/_img/search_cat_dropdown_arrow.gif';
	this.redArrow = '/_img/search_cat_selected_arrow.gif';
}

AnythingSearchManager.prototype.initialize = function(search_type) {
	if (!search_type){
		search_type = this.base_search_cats[0];
	}

	// Add hidden imput to replace radio buttons
	var search = '<input type="hidden" name="search_type" id="search_type" value="'+search_type+'"/>';

	search += '<ul id="SearchCategoriesList" class="SearchCategoriesList">';

	if (search_type == 'Forum') {
		search_type = 'Community';
	}

	for(var i=0, len=this.base_search_cats.length; i<len; ++i) {
		var cat = this.base_search_cats[i];
		var selected = search_type == cat ? 'selectedCat'  : 'unselectedCat';

		search += '<li id="search_type_li_'+cat+'" onclick="anythingSearchManager.clickCat(\''+cat+'\',event)" class='+selected+'><a id="search_type_'+cat +'" href="#" class='+selected+'>'+cat+'</a>|</li>';
	}

	var moreClass = 'unselectedCat';
	var moreText = 'More';
	var moreDropdown = '<div id="SearchDropdown" style="display:none">';
	var moreImg = this.blueArrow;
	for(var i=0, len=this.more_search_cats.length; i<len; ++i) {
		var cat = this.more_search_cats[i];
		moreDropdown += '<a id="search_type_'+cat +'" href="#" onclick="anythingSearchManager.clickMoreCat(\''+cat+'\',event)">'+cat+'</a>';
		if(search_type == cat || (search_type == 'Forum' && cat == 'Community')){
			moreClass = 'selectedMore'
			moreText = cat;
			var moreImg = this.redArrow;
		}
	}
	moreDropdown += '</div>';

	search += '<li id="search_type_li_More" onclick="anythingSearchManager.clickMore(event)" class='+moreClass+'><a id="search_type_More" href="#" class='+moreClass+'>'+moreText+' </a>'+moreDropdown+'</li><li onclick="anythingSearchManager.clickMore(event)"><img class="hand" src="'+moreImg+'" id="anythingSearchDropdownImg"></li></ul><br clear="both"/>';

	document.getElementById("SearchCategoriesContainer").innerHTML = search;

	var oldEvt = document.onclick;
	document.onclick = function() { if (oldEvt) oldEvt(); document.getElementById('SearchDropdown').style.display = 'none';}
}

AnythingSearchManager.prototype.unselectAll = function() {
	for(var i=0, len=this.base_search_cats.length; i<len; ++i) {
		document.getElementById('search_type_li_'+this.base_search_cats[i]).className = 'unselectedCat';
		document.getElementById('search_type_' + this.base_search_cats[i]).className = 'unselectedCat';
	}
	document.getElementById('search_type_More').className = 'unselectedCat';
	document.getElementById('search_type_More').innerHTML = 'More';
	this.dropDownImgUnselected();
}

AnythingSearchManager.prototype.dropDownImgSelected = function() {
	document.getElementById('anythingSearchDropdownImg').src = this.redArrow;
}

AnythingSearchManager.prototype.dropDownImgUnselected = function() {
	document.getElementById('anythingSearchDropdownImg').src = this.blueArrow;
}

AnythingSearchManager.prototype.clickCat = function(cat, event) {
	this.unselectAll();

	document.getElementById('search_type').value = cat == 'Community' ? 'Forum' : cat;

	document.getElementById('search_type_li_'+cat).className = 'selectedCat';
	document.getElementById('search_type_'+cat).className = 'selectedCat';

	if (!event) {
		event = window.event;
	}
	event = new Event(event);
	event.stop();
	this.hideDropdown();
}

AnythingSearchManager.prototype.clickMoreCat = function(cat, event) {
	this.unselectAll();

	document.getElementById('search_type').value = cat == 'Community' ? 'Forum' : cat;

	var moreLink = document.getElementById('search_type_More');
	moreLink.innerHTML = cat;
	moreLink.className = 'selectedMore';
	document.getElementById('search_type_li_More').className = 'selectedMore';

	this.dropDownImgSelected();

	if (!event) {
		event = window.event;
	}
	event = new Event(event);
	event.stop();
	this.hideDropdown();
}


AnythingSearchManager.prototype.clickMore = function(event) {
	if (!event) {
		event = window.event;
	}

	// stop so the document onclick to close the dropdown doesn't fire
	event.cancelBubble = true;
	if (event.stopPropagation) event.stopPropagation();

	if(document.getElementById('SearchDropdown').style.display == 'none') {
		document.getElementById('SearchDropdown').style.display = 'block';
	} else {
		document.getElementById('SearchDropdown').style.display = 'none';
	}
}

AnythingSearchManager.prototype.hideDropdown = function() {
	var sdd = document.getElementById('SearchDropdown');
	if(!sdd)
		return;

	sdd.style.display = 'none';
}

function initFormDefaults()
{
	if(typeof(MooTools) == 'undefined')
		return;
	if(MooTools.version == '1.11')
		return;


	var dwDefaults = new Class({
		//implements
		Implements: [Options],

		//options
		options: {
			collection: $$('input[alt]')
		},
		
		//initialization
		initialize: function(options) {
			//set options
			this.setOptions(options);
			this.defaults();
		},
		
		//a method that does whatever you want
		defaults: function() {
			this.options.collection.each(function(el) {
				
				el.set('value',el.get('alt'));
				el.addClass('default_input');
				
				el.addEvent('focus', function() {
					if(el.get('value') == el.get('alt'))
					{
						el.set('value','');
						el.removeClass('default_input');
					} 
				});
				el.addEvent('blur', function() {
					if(el.get('value') == '')
					{ 
						el.set('value',el.get('alt'));
						el.addClass('default_input');
					}
				});
			});
		}
	});

	window.addEvent('domready', function() {
		var defs = new dwDefaults({collection: $$('input[alt]')});
	});
}

initFormDefaults();