/*
 * Copyright 2007-2008 by Tobia Conforto <tobia.conforto@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * Versions: 0.1    2007-08-19  Initial release
 *                  2008-08-21  Re-released under GPL v2
 *           0.1.1  2008-09-18  Compatibility with prototype.js
 *           0.2    2008-10-15  Linkable images, contributed by Tim Rainey <tim@zmlabs.com>
 *           0.3    2008-10-22  Added option to repeat the animation a number of times, then stop
 *           0.3.1  2008-11-11  Better error messages
 *           0.3.2  2008-11-11  Fixed a couple of CSS bugs, contributed by Erwin Bot <info@ixgcms.nl>
 */

jQuery.fn.crossSlide = function(opts, plan) {
	var self = this,
			self_width = this.width(),
			self_height = this.height();

	// generic utilities
	function format(str) {
		for (var i = 1; i < arguments.length; i++)
			str = str.replace(new RegExp('\\{' + (i-1) + '}', 'g'), arguments[i]);
		return str;
	}

	function abort() {
		arguments[0] = 'crossSlide: ' + arguments[0];
		throw format.apply(null, arguments);
	}

	// first preload all the images, while getting their actual width and height
	(function(proceed) {

		var n_loaded = 0;
		function loop(i, img) {
			// for (i = 0; i < plan.length; i++) but with independent var i, img (for the closures)
			img.onload = function(e) {
				n_loaded++;
				plan[i].width = img.width;
				plan[i].height = img.height;
				if (n_loaded == plan.length)
					proceed();
			}
			img.src = plan[i].src;
			if (i + 1 < plan.length)
				loop(i + 1, new Image());
		}
		loop(0, new Image());

	})(function() {  // then proceed

		// utility to parse "from" and "to" parameters
		function parse_position_param(param) {
			var zoom = 1;
			var tokens = param.replace(/^\s*|\s*$/g, '').split(/\s+/);
			if (tokens.length > 3) throw new Error();
			if (tokens[0] == 'center')
				if (tokens.length == 1)
					tokens = ['center', 'center'];
				else if (tokens.length == 2 && tokens[1].match(/^[\d.]+x$/i))
					tokens = ['center', 'center', tokens[1]];
			if (tokens.length == 3)
				zoom = parseFloat(tokens[2].match(/^([\d.]+)x$/i)[1]);
			var pos = tokens[0] + ' ' + tokens[1];
			if (pos == 'left top'      || pos == 'top left')      return { xrel:  0, yrel:  0, zoom: zoom };
			if (pos == 'left center'   || pos == 'center left')   return { xrel:  0, yrel: .5, zoom: zoom };
			if (pos == 'left bottom'   || pos == 'bottom left')   return { xrel:  0, yrel:  1, zoom: zoom };
			if (pos == 'center top'    || pos == 'top center')    return { xrel: .5, yrel:  0, zoom: zoom };
			if (pos == 'center center')                           return { xrel: .5, yrel: .5, zoom: zoom };
			if (pos == 'center bottom' || pos == 'bottom center') return { xrel: .5, yrel:  1, zoom: zoom };
			if (pos == 'right top'     || pos == 'top right')     return { xrel:  1, yrel:  0, zoom: zoom };
			if (pos == 'right center'  || pos == 'center right')  return { xrel:  1, yrel: .5, zoom: zoom };
			if (pos == 'right bottom'  || pos == 'bottom right')  return { xrel:  1, yrel:  1, zoom: zoom };
			return {
				xrel: parseInt(tokens[0].match(/^(\d+)%$/)[1]) / 100,
				yrel: parseInt(tokens[1].match(/^(\d+)%$/)[1]) / 100,
				zoom: zoom
			};
		}

		// utility to compute the css for a given phase between p.from and p.to
		// phase = 1: begin fade-in,  2: end fade-in,  3: begin fade-out,  4: end fade-out
		function position_to_css(p, phase) {
			switch (phase) {
				case 1:
					var pos = 0;
					break;
				case 2:
					var pos = fade_ms / (p.time_ms + 2 * fade_ms);
					break;
				case 3:
					var pos = 1 - fade_ms / (p.time_ms + 2 * fade_ms);
					break;
				case 4:
					var pos = 1;
					break;
			}
			return {
				left:   Math.round(p.from.left   + pos * (p.to.left   - p.from.left  )),
				top:    Math.round(p.from.top    + pos * (p.to.top    - p.from.top   )),
				width:  Math.round(p.from.width  + pos * (p.to.width  - p.from.width )),
				height: Math.round(p.from.height + pos * (p.to.height - p.from.height))
			};
		}

		// check global params
		if (! opts.fade)
			abort('missing fade parameter.');
		if (opts.speed && opts.sleep)
			abort('you cannot set both speed and sleep at the same time.');
		// conversion from sec to ms; from px/sec to px/ms
		var fade_ms = Math.round(opts.fade * 1000);
		if (opts.sleep)
			var sleep = Math.round(opts.sleep * 1000);
		if (opts.speed)
			var speed = opts.speed / 1000,
					fade_px = Math.round(fade_ms * speed);

		// set container css
		self.empty().css({
			overflow: 'hidden',
			padding: 0
		});
		if (! self.css('position').match(/absolute|relative|fixed/))
			self.css({ position: 'relative' });
		if (! self.width() || ! self.height())
			abort('container element does not have its own width and height');

		// prepare each image
		for (var i = 0; i < plan.length; ++i) {

			var p = plan[i];
			if (! p.src)
				abort('missing src parameter in picture {0}.', i + 1);

			if (speed) { // speed/dir mode

				// check parameters and translate speed/dir mode into full mode (from/to/time)
				switch (p.dir) {
					case 'up':
						p.from = { xrel: .5, yrel: 0, zoom: 1 };
						p.to   = { xrel: .5, yrel: 1, zoom: 1 };
						var slide_px = p.height - self_height - 2 * fade_px;
						break;
					case 'down':
						p.from = { xrel: .5, yrel: 1, zoom: 1 };
						p.to   = { xrel: .5, yrel: 0, zoom: 1 };
						var slide_px = p.height - self_height - 2 * fade_px;
						break;
					case 'left':
						p.from = { xrel: 0, yrel: .5, zoom: 1 };
						p.to   = { xrel: 1, yrel: .5, zoom: 1 };
						var slide_px = p.width - self_width - 2 * fade_px;
						break;
					case 'right':
						p.from = { xrel: 1, yrel: .5, zoom: 1 };
						p.to   = { xrel: 0, yrel: .5, zoom: 1 };
						var slide_px = p.width - self_width - 2 * fade_px;
						break;
					default:
						abort('missing or malformed "dir" parameter in picture {0}.', i + 1);
				}
				if (slide_px <= 0)
					abort('picture number {0} is too short for the desired fade duration.', i + 1);
				p.time_ms = Math.round(slide_px / speed);

			} else if (! sleep) { // full mode

				// check and parse parameters
				if (! p.from || ! p.to || ! p.time)
					abort('missing either speed/sleep option, or from/to/time params in picture {0}.', i + 1);
				try {
					p.from = parse_position_param(p.from)
				} catch (e) {
					abort('malformed "from" parameter in picture {0}.', i + 1);
				}
				try {
					p.to = parse_position_param(p.to)
				} catch (e) {
					abort('malformed "to" parameter in picture {0}.', i + 1);
				}
				if (! p.time)
					abort('missing "time" parameter in picture {0}.', i + 1);
				p.time_ms = Math.round(p.time * 1000)
			}

			// precalculate left/top/width/height bounding values
			if (p.from)
				jQuery.each([ p.from, p.to ], function(i, from_to) {
					from_to.width  = Math.round(p.width  * from_to.zoom);
					from_to.height = Math.round(p.height * from_to.zoom);
					from_to.left   = Math.round((self_width  - from_to.width)  * from_to.xrel);
					from_to.top    = Math.round((self_height - from_to.height) * from_to.yrel);
				});

			// append the image element to the container
			var html = p.href
					? format('<a href="{0}" target="_blank"><img src="{1}"/></a>', p.href, p.src)
					: format('<img src="{0}"/>', p.src);
			jQuery(html).appendTo(self).css({
				position: 'absolute',
				visibility: 'hidden',
				top: 0,
				left: 0
			}).find('img').css({
				border: 0
			})
		}
		speed = undefined;  // speed mode has now been translated to full mode

		var imgs = self.children();

		// show first image
		imgs.eq(0).css({ visibility: 'visible' });
		if (! sleep)
			imgs.eq(0).css(position_to_css(plan[0], 2));

		// create animation chain
		var countdown = opts.loop;
		function create_chain(i, chainf) {
			// building the chain backwards, or inside out

			if (i % 2 == 0) {
				if (sleep) {

					// still image sleep

					var i_sleep = i / 2,
							i_hide = (i_sleep - 1 + plan.length) % plan.length,
							img_sleep = imgs.eq(i_sleep),
							img_hide = imgs.eq(i_hide);

					var newf = function() {
						img_hide.css('visibility', 'hidden');
						setTimeout(chainf, sleep);
					};

				} else {

					// single image slide

					var i_slide = i / 2,
							i_hide = (i_slide - 1 + plan.length) % plan.length,
							img_slide = imgs.eq(i_slide),
							img_hide = imgs.eq(i_hide),
							time = plan[i_slide].time_ms,
							slide_anim = position_to_css(plan[i_slide], 3);

					var newf = function() {
						img_hide.css('visibility', 'hidden');
						img_slide.animate(slide_anim, time, 'linear', chainf);
					};

				}
			} else {
				if (sleep) {

					// still image cross-fade

					var i_from = Math.floor(i / 2),
							i_to = Math.ceil(i / 2) % plan.length,
							img_from = imgs.eq(i_from),
							img_to = imgs.eq(i_to),
							from_anim = {},
							to_init = { visibility: 'visible' },
							to_anim = {};

					if (i_to > i_from) {
						to_init.opacity = 0;
						to_anim.opacity = 1;
					} else {
						from_anim.opacity = 0;
					}

					var newf = function() {
						img_to.css(to_init);
						if (from_anim.opacity != undefined)
							img_from.animate(from_anim, fade_ms, 'linear', chainf);
						else
							img_to.animate(to_anim, fade_ms, 'linear', chainf);
					};

				} else {

					// cross-slide + cross-fade

					var i_from = Math.floor(i / 2),
							i_to = Math.ceil(i / 2) % plan.length,
							img_from = imgs.eq(i_from),
							img_to = imgs.eq(i_to),
							from_anim = position_to_css(plan[i_from], 4),
							to_init = position_to_css(plan[i_to], 1),
							to_anim = position_to_css(plan[i_to], 2);

					if (i_to > i_from) {
						to_init.opacity = 0;
						to_anim.opacity = 1;
					} else {
						from_anim.opacity = 0;
					}
					to_init.visibility = 'visible';

					var newf = function() {
						img_from.animate(from_anim, fade_ms, 'linear');
						img_to.css(to_init);
						img_to.animate(to_anim, fade_ms, 'linear', chainf);
					};

				}
			}

			// if the loop option was requested, push a countdown check
			if (opts.loop && i == plan.length * 2 - 2) {
				var newf_orig = newf;
				newf = function() {
					if (--countdown) newf_orig();
				}
			}

			if (i > 0)
				return create_chain(i - 1, newf);
			else
				return newf;
		}
		var animation = create_chain(plan.length * 2 - 1, function() { return animation(); });

		// start animation
		animation();

	});

	return self;
};


/*
 * jQuery validation plug-in 1.4
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.validate.js 5788 2008-07-13 15:04:50Z joern.zaefferer $
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

(function($) {

$.extend($.fn, {
	// http://docs.jquery.com/Plugins/Validation/validate
	validate: function( options ) {
		
		// if nothing is selected, return nothing; can't chain anyway
		if (!this.length) {
			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
			return;
		}
		
		// check if a validator for this form was already created
		var validator = $.data(this[0], 'validator');
		if ( validator ) {
			return validator;
		}
		
		validator = new $.validator( options, this[0] );
		$.data(this[0], 'validator', validator); 
		
		if ( validator.settings.onsubmit ) {
		
			// allow suppresing validation by adding a cancel class to the submit button
			this.find("input, button").filter(".cancel").click(function() {
				validator.cancelSubmit = true;
			});
		
			// validate the form on submit
			this.submit( function( event ) {
				if ( validator.settings.debug )
					// prevent form submit to be able to see console output
					event.preventDefault();
					
				function handle() {
					if ( validator.settings.submitHandler ) {
						validator.settings.submitHandler.call( validator, validator.currentForm );
						return false;
					}
					return true;
				}
					
				// prevent submit for invalid forms or custom submit handlers
				if ( validator.cancelSubmit ) {
					validator.cancelSubmit = false;
					return handle();
				}
				if ( validator.form() ) {
					if ( validator.pendingRequest ) {
						validator.formSubmitted = true;
						return false;
					}
					return handle();
				} else {
					validator.focusInvalid();
					return false;
				}
			});
		}
		
		return validator;
	},
	// http://docs.jquery.com/Plugins/Validation/valid
	valid: function() {
        if ( $(this[0]).is('form')) {
            return this.validate().form();
        } else {
            var valid = false;
            var validator = $(this[0].form).validate();
            this.each(function() {
				valid |= validator.element(this);
            });
            return valid;
        }
    },
	// attributes: space seperated list of attributes to retrieve and remove
	removeAttrs: function(attributes) {
		var result = {},
			$element = this;
		$.each(attributes.split(/\s/), function() {
			result[this] = $element.attr(this);
			$element.removeAttr(this);
		});
		return result;
	},
	// http://docs.jquery.com/Plugins/Validation/rules
	rules: function(command, argument) {
		var element = this[0];
		
		if (command) {
			var staticRules = $.data(element.form, 'validator').settings.rules;
			var existingRules = $.validator.staticRules(element);
			switch(command) {
			case "add":
				$.extend(existingRules, $.validator.normalizeRule(argument));
				staticRules[element.name] = existingRules;
				break;
			case "remove":
				if (!argument) {
					delete staticRules[element.name];
					return existingRules;
				}
				var filtered = {};
				$.each(argument.split(/\s/), function(index, method) {
					filtered[method] = existingRules[method];
					delete existingRules[method];
				});
				return filtered;
			}
		}
		
		var data = $.validator.normalizeRules(
		$.extend(
			{},
			$.validator.metadataRules(element),
			$.validator.classRules(element),
			$.validator.attributeRules(element),
			$.validator.staticRules(element)
		), element);
		
		// make sure required is at front
		if (data.required) {
			var param = data.required;
			delete data.required;
			data = $.extend({required: param}, data);
		}
		
		return data;
	},
	// destructive add
	push: function( t ) {
		return this.setArray( this.add(t).get() );
	}
});

// Custom selectors
$.extend($.expr[":"], {
	// http://docs.jquery.com/Plugins/Validation/blank
	blank: function(a) {return !$.trim(a.value);},
	// http://docs.jquery.com/Plugins/Validation/filled
	filled: function(a) {return !!$.trim(a.value);},
	// http://docs.jquery.com/Plugins/Validation/unchecked
	unchecked: function(a) {return !a.checked;}
});


$.format = function(source, params) {
	if ( arguments.length == 1 ) 
		return function() {
			var args = $.makeArray(arguments);
			args.unshift(source);
			return $.format.apply( this, args );
		};
	if ( arguments.length > 2 && params.constructor != Array  ) {
		params = $.makeArray(arguments).slice(1);
	}
	if ( params.constructor != Array ) {
		params = [ params ];
	}
	$.each(params, function(i, n) {
		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
	});
	return source;
};

// constructor for validator
$.validator = function( options, form ) {
	this.settings = $.extend( {}, $.validator.defaults, options );
	this.currentForm = form;
	this.init();
};

$.extend($.validator, {

	defaults: {
		messages: {},
		groups: {},
		rules: {},
		errorClass: "error",
		errorElement: "label",
		focusInvalid: true,
		errorContainer: $( [] ),
		errorLabelContainer: $( [] ),
		onsubmit: true,
		ignore: [],
		onfocusin: function(element) {
			this.lastActive = element;
				
			// hide error label and remove error class on focus if enabled
			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass );
				this.errorsFor(element).hide();
			}
		},
		onfocusout: function(element) {
			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
				this.element(element);
			}
		},
		onkeyup: function(element) {
			if ( element.name in this.submitted || element == this.lastElement ) {
				this.element(element);
			}
		},
		onclick: function(element) {
			if ( element.name in this.submitted )
				this.element(element);
		},
		highlight: function( element, errorClass ) {
			$( element ).addClass( errorClass );
		},
		unhighlight: function( element, errorClass ) {
			$( element ).removeClass( errorClass );
		}
	},

	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
	setDefaults: function(settings) {
		$.extend( $.validator.defaults, settings );
	},

	messages: {
		required: "Dit veld is verplicht.",
		remote: "Please fix this field.",
		email: "Vul een geldig emailadres in.",
		url: "Please enter a valid URL.",
		date: "Please enter a valid date.",
		dateISO: "Please enter a valid date (ISO).",
		dateDE: "Bitte geben Sie ein gültiges Datum ein.",
		number: "Please enter a valid number.",
		numberDE: "Bitte geben Sie eine Nummer ein.",
		digits: "Please enter only digits",
		creditcard: "Please enter a valid credit card.",
		equalTo: "Please enter the same value again.",
		accept: "Please enter a value with a valid extension.",
		maxlength: $.format("Please enter no more than {0} characters."),
		minlength: $.format("Please enter at least {0} characters."),
		rangelength: $.format("Please enter a value between {0} and {1} characters long."),
		range: $.format("Please enter a value between {0} and {1}."),
		max: $.format("Please enter a value less than or equal to {0}."),
		min: $.format("Please enter a value greater than or equal to {0}.")
	},
	
	autoCreateRanges: false,
	
	prototype: {
		
		init: function() {
			this.labelContainer = $(this.settings.errorLabelContainer);
			this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
			this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
			this.submitted = {};
			this.valueCache = {};
			this.pendingRequest = 0;
			this.pending = {};
			this.invalid = {};
			this.reset();
			
			var groups = (this.groups = {});
			$.each(this.settings.groups, function(key, value) {
				$.each(value.split(/\s/), function(index, name) {
					groups[name] = key;
				});
			});
			var rules = this.settings.rules;
			$.each(rules, function(key, value) {
				rules[key] = $.validator.normalizeRule(value);
			});
			
			function delegate(event) {
				var validator = $.data(this[0].form, "validator");
				validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] );
			}
			$(this.currentForm)
				.delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate)
				.delegate("click", ":radio, :checkbox", delegate);
		},

		// http://docs.jquery.com/Plugins/Validation/Validator/form
		form: function() {
			this.checkForm();
			$.extend(this.submitted, this.errorMap);
			this.invalid = $.extend({}, this.errorMap);
			if (!this.valid())
				$(this.currentForm).triggerHandler("invalid-form.validate", [this]);
			this.showErrors();
			return this.valid();
		},
		
		checkForm: function() {
			this.prepareForm();
			for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
				this.check( elements[i] );
			}
			return this.valid(); 
		},
		
		// http://docs.jquery.com/Plugins/Validation/Validator/element
		element: function( element ) {
			element = this.clean( element );
			this.lastElement = element;
			this.prepareElement( element );
			this.currentElements = $(element);
			var result = this.check( element );
			if ( result ) {
				delete this.invalid[element.name];
			} else {
				this.invalid[element.name] = true;
			}
			if ( !this.numberOfInvalids() ) {
				// Hide error containers on last error
				this.toHide.push( this.containers );
			}
			this.showErrors();
			return result;
		},

		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
		showErrors: function(errors) {
			if(errors) {
				// add items to error list and map
				$.extend( this.errorMap, errors );
				this.errorList = [];
				for ( var name in errors ) {
					this.errorList.push({
						message: errors[name],
						element: this.findByName(name)[0]
					});
				}
				// remove items from success list
				this.successList = $.grep( this.successList, function(element) {
					return !(element.name in errors);
				});
			}
			this.settings.showErrors
				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
				: this.defaultShowErrors();
		},
		
		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
		resetForm: function() {
			if ( $.fn.resetForm )
				$( this.currentForm ).resetForm();
			this.submitted = {};
			this.prepareForm();
			this.hideErrors();
			this.elements().removeClass( this.settings.errorClass );
		},
		
		numberOfInvalids: function() {
			return this.objectLength(this.invalid);
		},
		
		objectLength: function( obj ) {
			var count = 0;
			for ( var i in obj )
				count++;
			return count;
		},
		
		hideErrors: function() {
			this.addWrapper( this.toHide ).hide();
		},
		
		valid: function() {
			return this.size() == 0;
		},
		
		size: function() {
			return this.errorList.length;
		},
		
		focusInvalid: function() {
			if( this.settings.focusInvalid ) {
				try {
					$(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus();
				} catch(e) { /* ignore IE throwing errors when focusing hidden elements */ }
			}
		},
		
		findLastActive: function() {
			var lastActive = this.lastActive;
			return lastActive && $.grep(this.errorList, function(n) {
				return n.element.name == lastActive.name;
			}).length == 1 && lastActive;
		},
		
		elements: function() {
			var validator = this,
				rulesCache = {};
			
			// select all valid inputs inside the form (no submit or reset buttons)
			// workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
			return $([]).add(this.currentForm.elements)
			.filter(":input")
			.not(":submit, :reset, :image, [disabled]")
			.not( this.settings.ignore )
			.filter(function() {
				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
			
				// select only the first element for each name, and only those with rules specified
				if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
					return false;
				
				rulesCache[this.name] = true;
				return true;
			});
		},
		
		clean: function( selector ) {
			return $( selector )[0];
		},
		
		errors: function() {
			return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
		},
		
		reset: function() {
			this.successList = [];
			this.errorList = [];
			this.errorMap = {};
			this.toShow = $([]);
			this.toHide = $([]);
			this.formSubmitted = false;
			this.currentElements = $([]);
		},
		
		prepareForm: function() {
			this.reset();
			this.toHide = this.errors().push( this.containers );
		},
		
		prepareElement: function( element ) {
			this.reset();
			this.toHide = this.errorsFor(element);
		},
	
		check: function( element ) {
			element = this.clean( element );
			
			// if radio/checkbox, validate first element in group instead
			if (this.checkable(element)) {
				element = this.findByName( element.name )[0];
			}
			
			var rules = $(element).rules();
			var dependencyMismatch = false;
			for( method in rules ) {
				var rule = { method: method, parameters: rules[method] };
				try {
					var result = $.validator.methods[method].call( this, $.trim(element.value), element, rule.parameters );
					
					// if a method indicates that the field is optional and therefore valid,
					// don't mark it as valid when there are no other rules
					if ( result == "dependency-mismatch" ) {
						dependencyMismatch = true;
						continue;
					}
					dependencyMismatch = false;
					
					if ( result == "pending" ) {
						this.toHide = this.toHide.not( this.errorsFor(element) );
						return;
					}
					
					if( !result ) {
						this.formatAndAdd( element, rule );
						return false;
					}
				} catch(e) {
					this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
						 + ", check the '" + rule.method + "' method");
					throw e;
				}
			}
			if (dependencyMismatch)
				return;
			if ( this.objectLength(rules) )
				this.successList.push(element);
			return true;
		},
		
		// return the custom message for the given element and validation method
		// specified in the element's "messages" metadata
		customMetaMessage: function(element, method) {
			if (!$.metadata)
				return;
			
			var meta = this.settings.meta
				? $(element).metadata()[this.settings.meta]
				: $(element).metadata();
			
			return meta.messages && meta.messages[method];
		},
		
		// return the custom message for the given element name and validation method
		customMessage: function( name, method ) {
			var m = this.settings.messages[name];
			return m && (m.constructor == String
				? m
				: m[method]);
		},
		
		// return the first defined argument, allowing empty strings
		findDefined: function() {
			for(var i = 0; i < arguments.length; i++) {
				if (arguments[i] !== undefined)
					return arguments[i];
			}
			return undefined;
		},
		
		defaultMessage: function( element, method) {
			return this.findDefined(
				this.customMessage( element.name, method ),
				this.customMetaMessage( element, method ),
				// title is never undefined, so handle empty string as undefined
				element.title || undefined,
				$.validator.messages[method],
				"<strong>Warning: No message defined for " + element.name + "</strong>"
			);
		},
		
		formatAndAdd: function( element, rule ) {
			var message = this.defaultMessage( element, rule.method );
			if ( typeof message == "function" ) 
				message = message.call(this, rule.parameters, element);
			this.errorList.push({
				message: message,
				element: element
			});
			this.errorMap[element.name] = message;
			this.submitted[element.name] = message;
		},
		
		addWrapper: function(toToggle) {
			if ( this.settings.wrapper )
				toToggle.push( toToggle.parents( this.settings.wrapper ) );
			return toToggle;
		},
		
		defaultShowErrors: function() {
			for ( var i = 0; this.errorList[i]; i++ ) {
				var error = this.errorList[i];
				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass );
				this.showLabel( error.element, error.message );
			}
			if( this.errorList.length ) {
				this.toShow.push( this.containers );
			}
			if (this.settings.success) {
				for ( var i = 0; this.successList[i]; i++ ) {
					this.showLabel( this.successList[i] );
				}
			}
			if (this.settings.unhighlight) {
				for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
					this.settings.unhighlight.call( this, elements[i], this.settings.errorClass );
				}
			}
			this.toHide = this.toHide.not( this.toShow );
			this.hideErrors();
			this.addWrapper( this.toShow ).show();
		},
		
		validElements: function() {
			return this.currentElements.not(this.invalidElements());
		},
		
		invalidElements: function() {
			return $(this.errorList).map(function() {
				return this.element;
			});
		},
		
		showLabel: function(element, message) {
			var label = this.errorsFor( element );
			if ( label.length ) {
				// refresh error/success class
				label.removeClass().addClass( this.settings.errorClass );
			
				// check if we have a generated label, replace the message then
				label.attr("generated") && label.html(message);
			} else {
				// create label
				label = $("<" + this.settings.errorElement + "/>")
					.attr({"for":  this.idOrName(element), generated: true})
					.addClass(this.settings.errorClass)
					.html(message || "");
				if ( this.settings.wrapper ) {
					// make sure the element is visible, even in IE
					// actually showing the wrapped element is handled elsewhere
					label = label.hide().show().wrap("<" + this.settings.wrapper + ">").parent();
				}
				if ( !this.labelContainer.append(label).length )
					this.settings.errorPlacement
						? this.settings.errorPlacement(label, $(element) )
						: label.insertAfter(element);
			}
			if ( !message && this.settings.success ) {
				label.text("");
				typeof this.settings.success == "string"
					? label.addClass( this.settings.success )
					: this.settings.success( label );
			}
			this.toShow.push(label);
		},
		
		errorsFor: function(element) {
			return this.errors().filter("[@for='" + this.idOrName(element) + "']");
		},
		
		idOrName: function(element) {
			return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
		},

		checkable: function( element ) {
			return /radio|checkbox/i.test(element.type);
		},
		
		findByName: function( name ) {
			// select by name and filter by form for performance over form.find("[name=...]")
			var form = this.currentForm;
			return $(document.getElementsByName(name)).map(function(index, element) {
				return element.form == form && element.name == name && element  || null;
			});
		},
		
		getLength: function(value, element) {
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				return $("option:selected", element).length;
			case 'input':
				if( this.checkable( element) )
					return this.findByName(element.name).filter(':checked').length;
			}
			return value.length;
		},
	
		depend: function(param, element) {
			return this.dependTypes[typeof param]
				? this.dependTypes[typeof param](param, element)
				: true;
		},
	
		dependTypes: {
			"boolean": function(param, element) {
				return param;
			},
			"string": function(param, element) {
				return !!$(param, element.form).length;
			},
			"function": function(param, element) {
				return param(element);
			}
		},
		
		optional: function(element) {
			return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
		},
		
		startRequest: function(element) {
			if (!this.pending[element.name]) {
				this.pendingRequest++;
				this.pending[element.name] = true;
			}
		},
		
		stopRequest: function(element, valid) {
			this.pendingRequest--;
			// sometimes synchronization fails, make pendingRequest is never < 0
			if (this.pendingRequest < 0)
				this.pendingRequest = 0;
			delete this.pending[element.name];
			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
				$(this.currentForm).submit();
			}
		},
		
		previousValue: function(element) {
			return $.data(element, "previousValue") || $.data(element, "previousValue", previous = {
				old: null,
				valid: true,
				message: this.defaultMessage( element, "remote" )
			});
		}
		
	},
	
	classRuleSettings: {
		required: {required: true},
		email: {email: true},
		url: {url: true},
		date: {date: true},
		dateISO: {dateISO: true},
		dateDE: {dateDE: true},
		number: {number: true},
		numberDE: {numberDE: true},
		digits: {digits: true},
		creditcard: {creditcard: true}
	},
	
	addClassRules: function(className, rules) {
		className.constructor == String ?
			this.classRuleSettings[className] = rules :
			$.extend(this.classRuleSettings, className);
	},
	
	classRules: function(element) {
		var rules = {};
		var classes = $(element).attr('class');
		classes && $.each(classes.split(' '), function() {
			if (this in $.validator.classRuleSettings) {
				$.extend(rules, $.validator.classRuleSettings[this]);
			}
		});
		return rules;
	},
	
	attributeRules: function(element) {
		var rules = {};
		var $element = $(element);
		
		for (method in $.validator.methods) {
			var value = $element.attr(method);
			if (value) {
				rules[method] = value;
			}
		}
		
		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
			delete rules.maxlength;
		}
		
		return rules;
	},
	
	metadataRules: function(element) {
		if (!$.metadata) return {};
		
		var meta = $.data(element.form, 'validator').settings.meta;
		return meta ?
			$(element).metadata()[meta] :
			$(element).metadata();
	},
	
	staticRules: function(element) {
		var rules = {};
		var validator = $.data(element.form, 'validator');
		if (validator.settings.rules) {
			rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
		}
		return rules;
	},
	
	normalizeRules: function(rules, element) {
		// handle dependency check
		$.each(rules, function(prop, val) {
			// ignore rule when param is explicitly false, eg. required:false
			if (val === false) {
				delete rules[prop];
				return;
			}
			if (val.param || val.depends) {
				var keepRule = true;
				switch (typeof val.depends) {
					case "string":
						keepRule = !!$(val.depends, element.form).length;
						break;
					case "function":
						keepRule = val.depends.call(element, element);
						break;
				}
				if (keepRule) {
					rules[prop] = val.param !== undefined ? val.param : true;
				} else {
					delete rules[prop];
				}
			}
		});
		
		// evaluate parameters
		$.each(rules, function(rule, parameter) {
			rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
		});
		
		// clean number parameters
		$.each(['minlength', 'maxlength', 'min', 'max'], function() {
			if (rules[this]) {
				rules[this] = Number(rules[this]);
			}
		});
		$.each(['rangelength', 'range'], function() {
			if (rules[this]) {
				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
			}
		});
		
		if ($.validator.autoCreateRanges) {
			// auto-create ranges
			if (rules.min && rules.max) {
				rules.range = [rules.min, rules.max];
				delete rules.min;
				delete rules.max;
			}
			if (rules.minlength && rules.maxlength) {
				rules.rangelength = [rules.minlength, rules.maxlength];
				delete rules.minlength;
				delete rules.maxlength;
			}
		}
		
		// To support custom messages in metadata ignore rule methods titled "messages"
		if (rules.messages) {
			delete rules.messages
		}
		
		return rules;
	},
	
	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
	normalizeRule: function(data) {
		if( typeof data == "string" ) {
			var transformed = {};
			$.each(data.split(/\s/), function() {
				transformed[this] = true;
			});
			data = transformed;
		}
		return data;
	},
	
	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
	addMethod: function(name, method, message) {
		$.validator.methods[name] = method;
		$.validator.messages[name] = message;
		if (method.length < 3) {
			$.validator.addClassRules(name, $.validator.normalizeRule(name));
		}
	},

	methods: {

		// http://docs.jquery.com/Plugins/Validation/Methods/required
		required: function(value, element, param) {
			// check if dependency is met
			if ( !this.depend(param, element) )
				return "dependency-mismatch";
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				var options = $("option:selected", element);
				return options.length > 0 && ( element.type == "select-multiple" || ($.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);
			case 'input':
				if ( this.checkable(element) )
					return this.getLength(value, element) > 0;
			default:
				return value.length > 0;
			}
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/remote
		remote: function(value, element, param) {
			if ( this.optional(element) )
				return "dependency-mismatch";
			
			var previous = this.previousValue(element);
			
			if (!this.settings.messages[element.name] )
				this.settings.messages[element.name] = {};
			this.settings.messages[element.name].remote = typeof previous.message == "function" ? previous.message(value) : previous.message;
			
			if ( previous.old !== value ) {
				previous.old = value;
				var validator = this;
				this.startRequest(element);
				var data = {};
				data[element.name] = value;
				$.ajax({
					url: param,
					mode: "abort",
					port: "validate" + element.name,
					dataType: "json",
					data: data,
					success: function(response) {
						if ( !response ) {
							var errors = {};
							errors[element.name] =  response || validator.defaultMessage( element, "remote" );
							validator.showErrors(errors);
						} else {
							var submitted = validator.formSubmitted;
							validator.prepareElement(element);
							validator.formSubmitted = submitted;
							validator.successList.push(element);
							validator.showErrors();
						}
						previous.valid = response;
						validator.stopRequest(element, response);
					}
				});
				return "pending";
			} else if( this.pending[element.name] ) {
				return "pending";
			}
			return previous.valid;
		},

		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
		minlength: function(value, element, param) {
			return this.optional(element) || this.getLength(value, element) >= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
		maxlength: function(value, element, param) {
			return this.optional(element) || this.getLength(value, element) <= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
		rangelength: function(value, element, param) {
			var length = this.getLength(value, element);
			return this.optional(element) || ( length >= param[0] && length <= param[1] );
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/min
		min: function( value, element, param ) {
			return this.optional(element) || value >= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/max
		max: function( value, element, param ) {
			return this.optional(element) || value <= param;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/range
		range: function( value, element, param ) {
			return this.optional(element) || ( value >= param[0] && value <= param[1] );
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/email
		email: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(element.value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/url
		url: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(element.value);
		},
        
		// http://docs.jquery.com/Plugins/Validation/Methods/date
		date: function(value, element) {
			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
		dateISO: function(value, element) {
			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/dateDE
		dateDE: function(value, element) {
			return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/number
		number: function(value, element) {
			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/numberDE
		numberDE: function(value, element) {
			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/digits
		digits: function(value, element) {
			return this.optional(element) || /^\d+$/.test(value);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
		// based on http://en.wikipedia.org/wiki/Luhn
		creditcard: function(value, element) {
			if ( this.optional(element) )
				return "dependency-mismatch";
			// accept only digits and dashes
			if (/[^0-9-]+/.test(value))
				return false;
			var nCheck = 0,
				nDigit = 0,
				bEven = false;

			value = value.replace(/\D/g, "");

			for (n = value.length - 1; n >= 0; n--) {
				var cDigit = value.charAt(n);
				var nDigit = parseInt(cDigit, 10);
				if (bEven) {
					if ((nDigit *= 2) > 9)
						nDigit -= 9;
				}
				nCheck += nDigit;
				bEven = !bEven;
			}

			return (nCheck % 10) == 0;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/accept
		accept: function(value, element, param) {
			param = typeof param == "string" ? param : "png|jpe?g|gif";
			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
		equalTo: function(value, element, param) {
			return value == $(param).val();
		}
		
	}
	
});

})(jQuery);

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
;(function($) {
	var ajax = $.ajax;
	var pendingRequests = {};
	$.ajax = function(settings) {
		// create settings for compatibility with ajaxSetup
		settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
		var port = settings.port;
		if (settings.mode == "abort") {
			if ( pendingRequests[port] ) {
				pendingRequests[port].abort();
			}
			return (pendingRequests[port] = ajax.apply(this, arguments));
		}
		return ajax.apply(this, arguments);
	};
})(jQuery);

// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 

// provides triggerEvent(type: String, target: Element) to trigger delegated events
;(function($) {
	$.each({
		focus: 'focusin',
		blur: 'focusout'	
	}, function( original, fix ){
		$.event.special[fix] = {
			setup:function() {
				if ( $.browser.msie ) return false;
				this.addEventListener( original, $.event.special[fix].handler, true );
			},
			teardown:function() {
				if ( $.browser.msie ) return false;
				this.removeEventListener( original,
				$.event.special[fix].handler, true );
			},
			handler: function(e) {
				arguments[0] = $.event.fix(e);
				arguments[0].type = fix;
				return $.event.handle.apply(this, arguments);
			}
		};
	});
	$.extend($.fn, {
		delegate: function(type, delegate, handler) {
			return this.bind(type, function(event) {
				var target = $(event.target);
				if (target.is(delegate)) {
					return handler.apply(target, arguments);
				}
			});
		},
		triggerEvent: function(type, target) {
			return this.triggerHandler(type, [$.event.fix({ type: type, target: target })]);
		}
	})
})(jQuery);




// START YSHOUT

String.prototype.sReplace = function(find, replace) {
	return this.split(find).join(replace);
};

String.prototype.repeat = function(times) {
	var rep = new Array(times + 1);
	return rep.join(this);
}

var YShout = function() {
	var self = this;
	var args = arguments;
	$(document).ready(function() {
		self.init.apply(self, args);
	});
} 

var yShout;

YShout.prototype = {
	animSpeed: 300,
	p: [],
		
	init: function(options) {
		yShout = this;
		var self = this;
		
		this.initializing = true;
		
		var dOptions = {
			yPath: 'yshout/',
			log: 1
		};

		this.options = jQuery.extend(dOptions, options);

		this.postNum = 0;
		this.floodAttempt = 0;	
		
		// Correct for missing trailing /
		if ((this.options.yPath.length > 0) && (this.options.yPath.charAt(this.options.yPath.length - 1) != '/'))
			this.options.yPath += '/';
		
		if (this.options.yLink) {
			if (this.options.yLink.charAt(0) != '#')
				this.options.yLink = '#' + this.options.yLink;
		
			$(this.options.yLink).click(function() {
				self.openYShout.apply(self);
				return false;
			});
		}
		
		// Load YShout from a link, in-page
		if (this.options.h_loadlink) {
			$(this.options.h_loadlink).click(function() {
				$('#yshout').css('display', 'block');
				$(this).unbind('click').click(function() { return false; });
				return false;
			});
			this.load(true);
		} else
			this.load();
		

	},
	
	load: function(hidden) {
		if ($('#yshout').length == 0) return;

		if (hidden) $('#yshout').css('display', 'none');
		
		this.ajax(this.initialLoad, { 
			reqType: 'init',
			yPath: this.options.yPath,
			log: this.options.log
		});
	},
	
	initialLoad: function(updates) {
		if (updates.yError) alert('There appears to be a problem: \n' + updates.yError + '\n\nIf you haven\'t already, try chmodding everything inside the YShout directory to 777.');
		this.d('In initialLoad');
		var self = this;
		
		this.prefs = jQuery.extend(updates.prefs, this.options.prefs);
		this.initForm();
		this.initRefresh();
		this.initLinks();
		if (this.prefs.flood) this.initFlood();

		if (updates.nickname)
			$('#ys-input-nickname')
				.removeClass('ys-before-focus')
				.addClass( 'ys-after-focus')
				.val(updates.nickname);

		if (updates)
			this.updates(updates);
	
		
		if (!this.prefs.doTruncate) {
			$('#ys-posts').css('height', $('#ys-posts').height + 'px');
		}

		if (!this.prefs.inverse) {
			var postsDiv = $('#ys-posts')[0];
			postsDiv.scrollTop = postsDiv.scrollHeight;
		}

		this.markEnds();
		
		this.initializing = false;
	},

	initForm: function() {
		this.d('In initForm');

		var postForm = 
			'<form id="ys-post-form"' + (this.prefs.inverse ? 'class="ys-inverse"' : '' ) + '><fieldset>' +
				'<input id="ys-input-nickname" value="' + this.prefs.defaultNickname + '" type="text" accesskey="N" maxlength="' + this.prefs.nicknameLength + '" class="ys-before-focus" />' +
				'<input id="ys-input-message" value="' + this.prefs.defaultMessage + '" type="text" accesskey="M" maxlength="' + this.prefs.messageLength + '" class="ys-before-focus" />' +
				(this.prefs.showSubmit ? '<input id="ys-input-submit" value="' + this.prefs.defaultSubmit + '" accesskey="S" type="submit" />' : '') +
				(this.prefs.postFormLink == 'cp' ? '<a title="View YShout Control Panel" class="ys-post-form-link" id="ys-cp-link" href="' + this.options.yPath + 'cp/">Admin CP</a>' : '') +
				(this.prefs.postFormLink == 'history' ? '<a title="Toon Shoutbox Geschiedenis" class="ys-post-form-link" id="ys-history-link" href="' + this.options.yPath + 'history/?log=' + this.options.log + '">Toon Geschiedenis</a>' : '') +
			'</fieldset></form>';

		var postsDiv = '<div id="ys-posts"></div>';

		if (this.prefs.inverse) $('#yshout').html(postForm + postsDiv);
		else $('#yshout').html(postsDiv + postForm);
		
		$('#ys-posts')
			.before('<div id="ys-before-posts"></div>')
			.after('<div id="ys-after-posts"></div>');
		
		$('#ys-post-form')
			.before('<div id="ys-before-post-form"></div>')
			.after('<div id="ys-after-post-form"></div>');
		
		var self = this;

		var defaults = { 
			'ys-input-nickname': self.prefs.defaultNickname, 
			'ys-input-message': self.prefs.defaultMessage
		};

		var keypress = function(e) { 
			var key = window.event ? e.keyCode : e.which; 
			if (key == 13 || key == 3) {
				self.send.apply(self);
				return false;
			}
		};

		var focus = function() { 
			if (this.value == defaults[this.id])
				$(this).removeClass('ys-before-focus').addClass( 'ys-after-focus').val('');
		};

		var blur = function() { 
			if (this.value == '')
				$(this).removeClass('ys-after-focus').addClass('ys-before-focus').val(defaults[this.id]); 
		};

		$('#ys-input-message').keypress(keypress).focus(focus).blur(blur);
		$('#ys-input-nickname').keypress(keypress).focus(focus).blur(blur);

		$('#ys-input-submit').click(function(){ self.send.apply(self) });
		$('#ys-post-form').submit(function(){ return false });
	},

	initRefresh: function() {
		var self = this;
		if (this.refreshTimer) clearInterval(this.refreshTimer)
		this.refreshTimer = setInterval(function() {
			self.ajax(self.updates, { reqType: 'refresh' });
		}, this.prefs.refresh); // ! 3000..?
	},

	initFlood: function() {
		this.d('in initFlood');
		var self = this;
		this.floodCount = 0;
		this.floodControl = false;

		this.floodTimer = setInterval(function() {
			self.floodCount = 0;
		}, this.prefs.floodTimeout);
	},

	initLinks: function() {
		if ($.browser.msie) return;
		
		var self = this;

		$('#ys-cp-link').click(function() {
			self.openCP.apply(self);
			return false;
		});

		$('#ys-history-link').click(function() {
			self.openHistory.apply(self);
			return false;
		});

	},
	
	openCP: function() {
		var self = this;
		if (this.cpOpen) return;
		this.cpOpen = true;
		
		var url = this.options.yPath + 'cp/';

		$('body').append('<div id="ys-overlay"></div><div class="ys-window" id="ys-cp"><a title="Control Panel Afsluiten" href="#" id="ys-closeoverlay-link">Sluiten</a><a title="Toon Geschiedenis" href="#" id="ys-switchoverlay-link">Toon Geschiedenis</a><object class="ys-browser" id="cp-browser" data="' + url +'" type="text/html">Something went horribly wrong.</object></div>');

		$('#ys-overlay, #ys-closeoverlay-link').click(function() { 
			self.reload.apply(self, [true]);
			self.closeCP.apply(self);
			return false; 
		}); 
		
		$('#ys-switchoverlay-link').click(function() { 
			self.closeCP.apply(self);
			self.openHistory.apply(self);
			return false;
		});

	},

	closeCP: function() {
		this.cpOpen = false;
		$('#ys-overlay, #ys-cp').remove();
	},

	openHistory: function() {
		var self = this;
		if (this.hOpen) return;
		this.hOpen = true;
		var url = this.options.yPath + 'history/?log='+ this.options.log;
		$('body').append('<div id="ys-overlay"></div><div class="ys-window" id="ys-history"><a title="Sluiten" href="#" id="ys-closeoverlay-link">Sluiten</a><a title="Control Panel" href="#" id="ys-switchoverlay-link">View Admin CP</a><object class="ys-browser" id="history-browser" data="' + url +'" type="text/html">Something went horribly wrong.</object></div>');

		$('#ys-overlay, #ys-closeoverlay-link').click(function() { 
			self.reload.apply(self, [true]);
			self.closeHistory.apply(self);
			return false; 
		}); 

		$('#ys-switchoverlay-link').click(function() { 
			self.closeHistory.apply(self);
			self.openCP.apply(self);
			return false;
		});

	},

	closeHistory: function() {
		this.hOpen = false;
		$('#ys-overlay, #ys-history').remove();
	},
	
	openYShout: function() {
		var self = this;
		if (this.ysOpen) return;
		this.ysOpen = true;
		url = this.options.yPath + 'example/yshout.html';

		$('body').append('<div id="ys-overlay"></div><div class="ys-window" id="ys-yshout"><a title="Shoutbox Sluiten" href="#" id="ys-closeoverlay-link">Sluiten</a><object class="ys-browser" id="yshout-browser" data="' + url +'" type="text/html">Something went horribly wrong.</object></div>');
	
		$('#ys-overlay, #ys-closeoverlay-link').click(function() { 
			self.reload.apply(self, [true]);
			self.closeYShout.apply(self);
			return false; 
		}); 
	},

	closeYShout: function() {
		this.ysOpen = false;
		$('#ys-overlay, #ys-yshout').remove();
	},
	
	send: function() {
		if (!this.validate()) return;
		if (this.prefs.flood && this.floodControl) return;

		var  postNickname = $('#ys-input-nickname').val(), postMessage = $('#ys-input-message').val();

		if (postMessage == '/cp')
			this.openCP();
		else if (postMessage == '/history')
			this.openHistory();
		else
			this.ajax(this.updates, {
				reqType: 'post',
				nickname: postNickname,
				message: postMessage
			});

		$('#ys-input-message').val('')

		if (this.prefs.flood) this.flood();
	},

	validate: function() {
		var nickname = $('#ys-input-nickname').val(),
				message = $('#ys-input-message').val(),
				error = false;

		var showInvalid = function(input) {
			$(input).removeClass('ys-input-valid').addClass('ys-input-invalid')[0].focus();
			error = true;
		}

		var showValid = function(input) {
			$(input).removeClass('ys-input-invalid').addClass('ys-input-valid');
		}

		if (nickname == '' ||	nickname == this.prefs.defaultNickname)
			showInvalid('#ys-input-nickname');
		else
			showValid('#ys-input-nickname');

		if (message == '' || message == this.prefs.defaultMessage)
			showInvalid('#ys-input-message');
		else
			showValid('#ys-input-message');

		return !error;
	},

	flood: function() {
		var self = this;
		this.d('in flood');
		if (this.floodCount < this.prefs.floodMessages) {
			this.floodCount++;
			return;
		}

		this.floodAttempt++;
		this.disable();

		if (this.floodAttempt == this.prefs.autobanFlood)
			this.banSelf('You have been banned for flooding the shoutbox!');
			
		setTimeout(function() {
			self.floodCount = 0;
			self.enable.apply(self);
		}, this.prefs.floodDisable);
	},

	disable: function () {
		$('#ys-input-submit')[0].disabled = true;
		this.floodControl = true;
	},

	enable: function () {
		$('#ys-input-submit')[0].disabled = false;
		this.floodControl = false;
	},
	
	findBySame: function(ip) {
		if (!$.browser.safari) return;
		
		var same = [];
		for (var i = 0; i < this.p.length; i++)
			if (this.p[i].adminInfo.ip == ip) 
				same.push(this.p[i]);
		
		for (var i = 0; i < same.length; i++) {
			$('#' + same[i].id).fadeTo(this.animSpeed, .8).fadeTo(this.animSpeed, 1);
		}
	},
	
	updates: function(updates) {
		if (!updates) return;
		if (updates.prefs) this.prefs = updates.prefs;
		if (updates.posts) this.posts(updates.posts);
		if (updates.banned) this.banned();
	},

	banned: function() {
		var self = this;
		clearInterval(this.refreshTimer);
		clearInterval(this.floodTimer);
		if (this.initializing)
			$('#ys-post-form').css('display', 'none');
		else
			$('#ys-post-form').fadeOut(this.animSpeed);
		
		if ($('#ys-banned').length == 0) {
			$('#ys-input-message')[0].blur();
			$('#ys-posts').append('<div id="ys-banned"><span>You\'re banned. Click <a href="#" id="ys-unban-self">here</a> to unban yourself if you\'re an admin. If you\'re not, go <a href="' + this.options.yPath + 'cp/" id="ys-banned-cp-link">log in</a>!</span></div>');

			$('#ys-banned-cp-link').click(function() {
				self.openCP.apply(self);
				return false;
			});
			
			$('#ys-unban-self').click(function() {
				self.ajax(function(json) {
					if (!json.error)
						self.unbanned();
					 else if (json.error == 'admin')
						alert('You can only unban yourself if you\'re an admin.');
				}, { reqType: 'unbanself' });
				return false;
			});
		}		
	},

	unbanned: function() {
		var self = this;
		$('#ys-banned').fadeOut(function() { $(this).remove(); });
		this.initRefresh();
		$('#ys-post-form').css('display', 'block').fadeIn(this.animSpeed, function(){
			self.reload();
		});
	},
	
	posts: function(p) {
		for (var i = 0; i < p.length; i++) {
			this.post(p[i]);
		}
		
		this.truncate();
		
		if (!this.prefs.inverse) {
			var postsDiv = $('#ys-posts')[0];
			postsDiv.scrollTop = postsDiv.scrollHeight;
		}
	},

	post: function(post) {
		var self = this;
	
		var pad = function(n) { return n > 9 ? n : '0' + n; };
		var date = function(ts) { return new Date(ts * 1000); };
		var time = function(ts) { 
			var d = date(ts);
			var h = d.getHours(), m = d.getMinutes();

			if (self.prefs.timestamp == 12) {
				h = (h > 12 ? h - 12 : h);
				if (h == 0) h = 12;
			}

			return pad(h) + ':' + pad(m);
		};

		var dateStr = function(ts) {
			var t = date(ts);

		  var Y = t.getFullYear();
		  var M = t.getMonth();
		  var D = t.getDay();
		  var d = t.getDate();
		  var day = ['Sunday', 'Maandag', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][D];
		  var mon = ['01', '02', '03', '04', '05', '06',
		             '07', '08', '09', '10', '11', '12'][M];

		  return d + '-' + mon + '-' + Y;
		};

		var self = this;

		this.postNum++;
		var id = 'ys-post-' + this.postNum;
		post.id = id;
		
		post.message = this.links(post.message);
		post.message = this.smileys(post.message);
		post.message = this.bbcode(post.message);
		var html = 
			'<div id="' + id + '" class="ys-post' + (post.admin ? ' ys-admin-post' : '') + (post.banned ? ' ys-banned-post' : '') + '">' +
				
				'<span class="ys-post-nickname">' + post.nickname + this.prefs.nicknameSeparator + '</span> ' +
				(this.prefs.timestamp> 0 ? '<span class="ys-post-timestamp">&nbsp;&nbsp;&nbsp;' + dateStr(post.timestamp) + ' om ' + time(post.timestamp)  + '</span> ' : '') +
				'<span class="ys-post-message">' + post.message + '</span> ' +
				'<span class="ys-post-info' + (this.prefs.info == 'overlay' ? ' ys-info-overlay' : ' ys-info-inline') + '">' + (post.adminInfo ? '<em>IP:</em> ' + post.adminInfo.ip + ', ' : '') + '<em>Posted:</em> ' + dateStr(post.timestamp) + ' om ' + time(post.timestamp)  + '.</span>' +
				
			'</div>';
		if (this.prefs.inverse) $('#ys-posts').prepend(html);
		else $('#ys-posts').append(html);
		
		this.p.push(post);

		$('#' + id)
			.find('.ys-post-nickname').click(function() {
				if (post.adminInfo)
					self.findBySame(post.adminInfo.ip);
			}).end()
			.find('.ys-info-link').toggle(
				function() { self.showInfo.apply(self, [id, this]); return false; },
				function() { self.hideInfo.apply(self, [id, this]); return false; })
			.end()
			.find('.ys-ban-link').click(
				function() { self.ban.apply(self, [post, id]); return false; })
			.end()
			.find('.ys-delete-link').click(
				function() { self.del.apply(self, [post, id]); return false; });
			
	},
	
	showInfo: function(id, el) {
		var jEl = $('#' + id + ' .ys-post-info');
		if (this.prefs.info == 'overlay')
			jEl.css('display', 'block').fadeIn(this.animSpeed);
		else
			jEl.slideDown(this.animSpeed);
		
		el.innerHTML ='Close Info'
		return false;
	},
	
	hideInfo: function(id, el) {
		var jEl = $('#' + id + ' .ys-post-info');
		if (this.prefs.info == 'overlay')
			jEl.fadeOut(this.animSpeed);
		else
			jEl.slideUp(this.animSpeed);
			
		el.innerHTML = 'Info';
		return false;
	}, 
	
	ban: function(post, id) {
		var self = this;

		var link = $('#' + id).find('.ys-ban-link')[0];

		switch(link.innerHTML) {
			case 'Ban':
				var pars = {
					reqType: 'ban',
					ip: post.adminInfo.ip,
					nickname: post.nickname
				};

				this.ajax(function(json) {
					if (json.error) {
						switch (json.error) {
							case 'admin':
								self.error('You\'re not an admin. Log in through the Admin CP to ban people.');
								break;
						}
						return;
					}
					//alert('p: ' + this.p + ' / ' + this.p.length);
					if (json.bannedSelf)
						self.banned(); // ?
						
					else 						
						$.each(self.p, function(i) {
							if (this.adminInfo && this.adminInfo.ip == post.adminInfo.ip) 
									$('#' + this.id)
										.addClass('ys-banned-post')
										.find('.ys-ban-link').html('Unban');
						});
						
				}, pars);
				
				link.innerHTML = 'Banning...';
				return false;
				break;
			
			case 'Banning...':
				return false;
				break;
			
			case 'Unban':
				var pars = {
					reqType: 'unban',
					ip: post.adminInfo.ip
				};
	
				this.ajax(function(json) {
					if (json.error) {
						switch(json.error) {
							case 'admin':
								self.error('You\'re not an admin. Log in through the Admin CP to unban people.');
								return;
								break;
						}
					}
					
					$.each(self.p, function(i) {
						if (this.adminInfo && this.adminInfo.ip == post.adminInfo.ip) 
							$('#' + this.id)
								.removeClass('ys-banned-post')
								.find('.ys-ban-link').html('Ban');
					});
					
				}, pars);
	
				link.innerHTML = 'Unbanning...';
				return false;
				break;
				
			case 'Unbanning...':
				return false;
				break;
		}
	},
	
	del: function(post, id) {
		var self = this;
		var link = $('#' + id).find('.ys-delete-link')[0];

		if (link.innerHTML == 'Deleting...') return;
	
		var pars = {
			reqType: 'delete',
			uid: post.uid
		};

		self.ajax(function(json) {
			if (json.error) {
				switch(json.error) {
					case 'admin':
						self.error('You\'re not an admin. Log in through the Admin CP to ban people.');
						return;
						break;
				}
			}
			self.reload();
		}, pars);

		link.innerHTML = 'Deleting...';
		return false;

	},
	
	banSelf: function(reason) {
		var self = this;

		this.ajax(function(json) {
			if (json.error == false)
				self.banned();
		}, {
			reqType: 'banself',
			nickname: $('#ys-input-nickname').val() 
		});
	},

	bbcode: function(s) {
		s = s.sReplace('[i]', '<i>');
		s = s.sReplace('[/i]', '</i>');
		s = s.sReplace('[I]', '<i>');
		s = s.sReplace('[/I]', '</i>');

		s = s.sReplace('[b]', '<b>');
		s = s.sReplace('[/b]', '</b>');
		s = s.sReplace('[B]', '<b>');
		s = s.sReplace('[/B]', '</b>');

		s = s.sReplace('[u]', '<u>');
		s = s.sReplace('[/u]', '</u>');
		s = s.sReplace('[U]', '<u>');
		s = s.sReplace('[/U]', '</u>');

		return s;
	},
	
	smileys: function(s) {
		var yp = this.options.yPath;
		
		var smile = function(str, smiley, image) {
			return str.sReplace(smiley, '<img src="' + yp + 'smileys/' + image + '" />');
		};

		s = smile(s, '(6)',  'twisted.gif');
		s = smile(s, ':\'(',  'cry.gif');
		s = smile(s, ':eek:',  'eek.gif');
		s = smile(s, ':evil:',  'evil.gif');
		s = smile(s, ':lol:',  'lol.gif');
		s = smile(s, ':mrgreen:',  'mrgreen.gif');
		s = smile(s, ':$',  'redface.gif');
		s = smile(s, '8-)',  'rolleyes.gif');
		s = smile(s, '8)',  'rolleyes.gif');

		s = smile(s, ':S',  'confused.gif');
		s = smile(s, ':s',  'confused.gif');
		s = smile(s, ':D',  'biggrin.gif');
		s = smile(s, ':d',  'biggrin.gif');
		s = smile(s, '(H)',  'cool.gif');
		s = smile(s, '(h)',  'cool.gif');
		s = smile(s, ':@',  'mad.gif');
		s = smile(s, ':|',  'neutral.gif');
		s = smile(s, ':P',  'razz.gif');
		s = smile(s, ':p',  'razz.gif');
		s = smile(s, ':(',  'sad.gif');
		s = smile(s, ':)',  'smile.gif');
		s = smile(s, ':O',  'surprised.gif');
		s = smile(s, ':o',  'surprised.gif');
		s = smile(s, ';)',  'wink.gif');

		return s;
	},

	links: function(s) {
		return s.replace(/((https|http|ftp|ed2k):\/\/[\S]+)/gi, '<a  href="$1" target="_blank">$1</a>');
	},

	truncate: function(clearAll) {
		var truncateTo = clearAll ? 0 : this.prefs.truncate;
		var posts = $('#ys-posts .ys-post').length;
		if (posts <= truncateTo) return;
		//alert(this.initializing);
		if (this.prefs.doTruncate || this.initializing) {
			var diff = posts - truncateTo;
			for (var i = 0; i < diff; i++)
				this.p.shift();
			
			//	$('#ys-posts .ys-post:gt(' + truncateTo + ')').remove();

			if (this.prefs.inverse) 
				$('#ys-posts .ys-post:gt(' + (truncateTo - 1) + ')').remove();
				else 
				$('#ys-posts .ys-post:lt(' + (posts - truncateTo) + ')').remove();
		}
		
		this.markEnds();		
	},
	
	markEnds: function() {
		$('#ys-posts')
			.find('.ys-first').removeClass('ys-first').end()
			.find('.ys-last').removeClass('ys-last');
			
		$('#ys-posts .ys-post:first-child').addClass('ys-first');
		$('#ys-posts .ys-post:last-child').addClass('ys-last');
	},
	
	reload: function(everything) {
		var self = this;
		this.initializing = true;
		
		if (everything) {
			this.ajax(function(json) { 
				$('#yshout').html(''); 
				clearInterval(this.refreshTimer);
				clearInterval(this.floodTimer);
				this.initialLoad(json); 
			}, { 
				reqType: 'init',
				yPath: this.options.yPath,
				log: this.options.log
			});
		} else {
			this.ajax(function(json) { this.truncate(true); this.updates(json); this.initializing = false; }, {
				reqType: 'reload'
			});
		}
	},

	error: function(str) {
		alert(str);
	},

	json: function(parse) {
		this.d('In json: ' + parse);
		var json = eval('(' + parse + ')');
		if (!this.checkError(json)) return json;
	},

	checkError: function(json) {
		if (!json.yError) return false;

		this.d('Error: ' + json.yError);
		return true;
	},

	ajax: function(callback, pars, html) {
		pars = jQuery.extend({
			reqFor: 'shout'
		}, pars);

		var self = this;

		$.post(this.options.yPath + 'yshout.php', pars, function(parse) {
			if (parse)
				if (html)
					callback.apply(self, [parse]);
				else
					callback.apply(self, [self.json(parse)]);
			else
				callback.apply(self);
		});
	},

	d: function(message) {
		$('#debug').css('display', 'block').prepend('<p>' + message + '</p>');
		return message;
	}
};

///piroBox START
/* __________________________________________________________________
		Name: piroBox v.1.1
		Date: february 2009
		Use: just  another gallery.
		Autor: Diego Valobra (http://www.pirolab.it),(http://www.diegovalobra.com)
		Version: 1.1
		Licence: CC-BY-SA http://creativecommons.org/licenses/by-sa/2.5/it/
_______________________________________________________________________________*/

$(document).ready(function(){$('body').append('<!-- :::::::: PIROBOX :::::::::: -->'+'<div class="pre"></div>'+'<div class="bg_thumbs"></div>'+'<div class="box_next"><a href="#" class="next" title="next image">next</a></div>'+'<div class="box_previous"><a href="#" class="previous" title="previous image">prev</a></div>'+'<div id="gallery" class="thumbs">'+'<div class="all">'+'<div class="t_l"></div>'+'<div class="t_r"></div>'+'<div class="middle_l"></div>'+'<div class="middle_r"></div>'+'<div class="t_l_b"></div>'+'<div class="t_r_b"></div>'+'<div class="img_box" title="close">'+'<div class="box_next_in"><a href="#" class="next_in" title="next image">next</a></div>'+'<div class="box_previous_in"><a href="#" class="previous_in" title="previous image">prev</a></div>'+'</div>'+'<span class="thumbs_close" title="close"></span>'+'</div>'+'</div>'+'<!-- :::::::: END PIROBOX :::::::::: -->');});(function($){$.fn.piroBox=function(opt){opt=jQuery.extend({border:1,mySpeed:null,open_speed:1000,close_speed:500,bg_alpha:0.5,pathLoader:null,gallery:null,gallery_li:null,single:null,next_class:null,previous_class:null,padding:'0',gloabal:true},opt);return this.each(function(){function closeIt(){$('.pre').hide();$('.caption').remove();$('li.begin').remove();$('li.end').remove();$('.thumbs_close').css('display','none');$(opt.next_class+','+opt.previous_class).css({'visibility':'hidden'});$((opt.gallery_li)).removeClass('start');$((opt.gallery_li)).removeClass('back');$('.box_next_in, .box_previous_in,.box_next,.box_previous ').css('display','none');$('.loader').fadeTo(300,0);$('.loader').queue(function(){$('.bg_thumbs').fadeTo(500,0);$('.img_box img').remove();$('.img_box ').queue(function(){$('.all').css({'top':'50%','height':'80px','width':'80px','marginLeft':'-45px','marginTop':'-40px','visibility':'hidden','padding':'10px'})
$('.img_box').css({'height':'50px','width':'50px','visibility':'hidden'}).removeClass('unloader');$('.bg_thumbs').hide().css('visibility','hidden');$('.thumbs').hide();$('.img_box').dequeue();});$('.loader').dequeue().remove('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');});$('.img_box img, .thumbs_close').fadeTo(400,0);$('.img_box img').queue(function(){$('.img_box').animate({height:'50px',width:'50px'},50).css('visibility','hidden');$('.all').animate({top:'50%',height:'80px',width:'80px',marginLeft:'-45px',marginTop:'-40px',padding:'10px'},(opt.close_speed));$('.img_box img').remove();$('.img_box').removeClass('unloader');$('.bg_thumbs').fadeTo(500,0);$('.all').queue(function(){$('.bg_thumbs,.thumbs_close').hide().css('visibility','hidden');$('.thumbs').css('display','none');$('.all').css('visibility','hidden').dequeue()});$('.img_box img').dequeue();});}
var next_out=$('.box_next').width();var idPiro=$(this).attr('id');var b_size=(opt.border)+2;if($.browser.msie&&$.browser.version<7){$('.img_box').css('padding','2px');$('head').append('<!--[if lte IE 6]>'+'<style type="text/css">@media screen{* html{overflow-y: hidden;}* html body{height: 100%;overflow: auto;}}</style>'+'<![endif]-->');}else{$('.img_box').css('padding','2px');(opt.mySpeed);}
$('.bg_thumbs, .thumbs, .thumbs_close ').hide();$(window).resize(function(){var new_w_bg=$(window).height();$('.bg_thumbs').css({'visibility':'visible','height':+new_w_bg+30+'px'});});var w_bg=$(window).height();$('.bg_thumbs').css({'visibility':'hidden','height':+w_bg+30+'px'});$(opt.gallery+','+opt.single).bind('click',function(){$(this).parent('li').parent('ul').prepend('<li  class="begin"></li>');$(this).parent('li').parent('ul').append('<li  class="end"></li>');$('.pre').append('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>').hide();$('.all').prepend('<div class="caption"><p title="caption"></p></div>');$('.caption').css({'opacity':'0','visibility':'hidden'});$(opt.next_class+','+opt.previous_class).css({'visibility':'hidden'});if($(this).parent().next('li').is('.end')||$(this).parent('span').is('.single')){$((opt.next_class)).css('right','-'+next_out-30+'px');$(this).parent().next('li').removeClass('start');}else{$((opt.next_class)).css('visibility','hidden').css({right:'0px'});$(this).parent().next('li').addClass('start');}
if($(this).parent().prev('li').is('.begin')||$(this).parent('span').is('.single')){$((opt.previous_class)).css('left','-'+next_out-30+'px');$('.box_next_in, .box_previous_in ').css('display','none');}else{$((opt.previous_class)).css('visibility','hidden').css({left:'0px'});$(this).parent().prev('li').addClass('back');}
$('.img_box img').remove('img');$(window).resize(function(){var new_w_bg=$(window).height();$('.bg_thumbs').css({'visibility':'visible','height':+new_w_bg+30+'px'});});var w_bg=$(window).height();$('.pre').css('visibility','visible').show();var pathImg=$(this).attr('href');var titleImg=$(this).attr('title');var myImg=new Image();$(myImg).load(function(){var imgH=myImg.height;var imgW=myImg.width;var w_H=$(window).height();var w_W=$(window).width();$('#'+idPiro+' .img_box').append(this);if(imgH+100>w_H||imgW+100>w_W){var new_img_W=imgW;var new_img_H=imgH;var _x=(imgW+100)/w_W;var _y=(imgH+100)/w_H;if(_y>_x){new_img_W=Math.round(imgW*(0.9/_y));new_img_H=Math.round(imgH*(0.9/_y));}else{new_img_W=Math.round(imgW*(0.9/_x));new_img_H=Math.round(imgH*(0.9/_x));}
imgH+=new_img_H;imgW+=new_img_W;$('.thumbs').show();$('.bg_thumbs').show().css({'opacity':'0','visibility':'visible','height':+w_bg+'px'}).fadeTo(300,(opt.bg_alpha));$('.img_box img').css('visibility','hidden').hide();$('.all').css({'visibility':'visible'}).animate({height:(new_img_H)+'px',width:(new_img_W)+'px',marginLeft:'-'+((new_img_W)/2)+'px',marginTop:'-'+((new_img_H)/2+20)+'px'},(opt.open_speed));$('.all').queue(function(){$('.img_box').css({visibility:'visible',height:(new_img_H)+'px',width:(new_img_W)+'px'});$('.img_box').queue(function(){$(myImg).height(new_img_H).width(new_img_W).css('opacity',0);$('.img_box img').css('visibility','visible').show().fadeTo(300,1);$('.img_box ').addClass('unloader');$('.loader').remove('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');$('.img_box').dequeue()
if(titleImg==""){$('.caption').css('visibility','hidden');$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(200,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});}else{$('.caption p').html(titleImg);var caption_h=$('.caption').height();$('.all').animate({height:new_img_H+(caption_h+10)+'px'},300);$('.all').queue(function(){$('.caption').css({'visibility':'visible','width':+new_img_W+'px'}).fadeTo(400,1);$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(200,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});$('.all').dequeue()});}});if($(opt.next_class).is('.next_in')){$('.box_next_in ,.box_previous_in ').css('display','block');$('.box_next,.box_previous ').css('display','none');$(opt.next_class+','+opt.previous_class).css({'visibility':'visible'});}else if($(opt.next_class).is('.next')){$('.box_next_in, .box_previous_in ').css('display','none');$('.box_next,.box_previous ').css('display','block');$(opt.next_class+','+opt.previous_class).css({'visibility':'visible'});}
$('.all').dequeue();});}else{$('.thumbs').show();$('.bg_thumbs').show().css({'opacity':'0','visibility':'visible','height':+w_bg+'px'}).fadeTo(300,(opt.bg_alpha));$('.img_box img').css('visibility','hidden').hide();$('.all').css({'visibility':'visible'}).animate({height:(imgH)+'px',width:(imgW)+'px',marginLeft:'-'+((imgW)/2)+'px',marginTop:'-'+((imgH)/2+10)+'px'},(opt.open_speed));$('.all').queue(function(){$('.img_box').css({visibility:'visible',height:(imgH)+'px',width:(imgW)+'px'});$('.img_box').queue(function(){$(myImg).height(imgH).width(imgW).css('opacity',0);$('.img_box img').css('visibility','visible').show().fadeTo(300,1);$('.img_box ').addClass('unloader');$('.loader').remove(' <div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');$('.img_box').dequeue()
if(titleImg==""){$('.caption').css('visibility','hidden');$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(200,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});}else{$('.caption p').html(titleImg);var caption_h=$('.caption').height();$('.all').animate({height:imgH+(caption_h+10)+'px'},300);$('.all').queue(function(){$('.caption').css({'visibility':'visible','width':+imgW+'px'}).fadeTo(400,1);$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(200,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});$('.all').dequeue()});}});if($(opt.next_class).is('.next_in')){$('.box_next_in ,.box_previous_in ').css('display','block');$('.box_next,.box_previous ').css('display','none');$(opt.next_class+','+opt.previous_class).css({'visibility':'visible'});}else if($(opt.next_class).is('.next')){$('.box_next_in, .box_previous_in ').css('display','none');$('.box_next,.box_previous ').css('display','block');$(opt.next_class+','+opt.previous_class).css({'visibility':'visible'});}
$('.all').dequeue();});}});$(myImg).attr('src',pathImg);return false;});$((opt.next_class)).bind('click',function(){$('.thumbs_close').css({'opacity':'0','visibility':'hidden'});$('.img_box img').remove('img');$('.pre').css('visibility','visible').show();$('.caption').css({'opacity':'0','visibility':'hidden'});$('.pre').append('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');var pathImg=$('.start>a').attr('href');var titleImg=$('.start>a').attr('title');$('.start').next('li').addClass('start');$('.start').queue(function(){$(this).prev('li').removeAttr('class');$((opt.gallery_li)).removeClass('back');$('.start').prev('li').prev('li').addClass('back');$((opt.previous_class)).animate({left:'0px'},300);$('.start').dequeue();});$((opt.next_class)).css('visibility','hidden');$((opt.previous_class)).css('visibility','hidden');var myImg=new Image();$(myImg).load(function(){var imgH=myImg.height;var imgW=myImg.width;var w_H=$(window).height();var w_W=$(window).width();$('#'+idPiro+' .img_box').append(this);if(imgH+100>w_H||imgW+100>w_W){var new_img_W=imgW;var new_img_H=imgH;var _x=(imgW+100)/w_W;var _y=(imgH+100)/w_H;if(_y>_x){new_img_W=Math.round(imgW*(0.9/_y));new_img_H=Math.round(imgH*(0.9/_y));}else{new_img_W=Math.round(imgW*(0.9/_x));new_img_H=Math.round(imgH*(0.9/_x));}
imgH+=new_img_H;imgW+=new_img_W;$('.thumbs').show();$('.img_box ').css('visibility','hidden');$('.img_box img').css('visibility','hidden').hide();$('.all').css({'visibility':'visible'}).animate({height:(new_img_H)+'px',width:(new_img_W)+'px',marginLeft:'-'+((new_img_W)/2)+'px',marginTop:'-'+((new_img_H)/2+20)+'px'},(opt.mySpeed));$('.all').queue(function(){$('.img_box').css({visibility:'visible',height:(new_img_H)+'px',width:(new_img_W)+'px'});$('.img_box').queue(function(){$(myImg).height(new_img_H).width(new_img_W).css('opacity',0);$('.img_box img').css('visibility','visible').show().fadeTo(200,1)
$('div.box_previous_in,div.box_previous').css({'display':'block'});$('.img_box ').addClass('unloader');$('.loader').remove('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');$('.img_box').dequeue()
if(titleImg==""){$('.caption').css('visibility','hidden');$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(300,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});}else{$('.caption p').html(titleImg);$('.caption').css({'width':+new_img_W+'px'});var caption_h=$('.caption').height();var caption_w=new_img_W;$('.all').animate({height:new_img_H+(caption_h+10)+'px'},300);$('.all').queue(function(){$('.caption').css({'visibility':'visible'}).fadeTo(600,1);$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(300,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});$('.all').dequeue()});}});if($(opt.next_class).is('.next_in')){$('.box_next_in ,.box_previous_in ').css('display','block');$('.box_next,.box_previous ').css('display','none');$(opt.next_class+','+opt.previous_class).css({'visibility':'visible'});}else if($(opt.next_class).is('.next')){$('.box_next_in, .box_previous_in ').css('display','none');$('.box_next,.box_previous ').css('display','block');$(opt.next_class+','+opt.previous_class).css({'visibility':'visible'});}
if($('.start ').is('li.end')){$((opt.next_class)).css('visibility','hidden');$('div.box_next_in,div.box_next').css({'display':'none'});$('.end').removeClass('start');$(opt.previous_class).css({'visibility':'visible'});}else{$(opt.next_class+','+opt.previous_class).css({'visibility':'visible'});}
$('.all').dequeue();});}else{$('.thumbs').show();$('.img_box ').css('visibility','hidden');$((opt.previous_class)).css('visibility','hidden');$('.img_box img').css('visibility','hidden').hide();$('.all').css({'visibility':'visible'}).animate({height:(imgH)+'px',width:(imgW)+'px',marginLeft:'-'+((imgW)/2)+'px',marginTop:'-'+((imgH)/2+10)+'px'},(opt.mySpeed));$('.all').queue(function(){$('.img_box').css({visibility:'visible',height:(imgH)+'px',width:(imgW)+'px'});$('.img_box').queue(function(){$(myImg).height(imgH).width(imgW).css('opacity',0);$('.img_box img').css('visibility','visible').show().fadeTo(200,1);$('div.box_previous_in,div.box_previous').css({'display':'block'});$('.img_box ').addClass('unloader');$('.loader').remove('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');$('.img_box').dequeue()
if(titleImg==""){$('.caption').css('visibility','hidden');$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(300,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});}else{$('.caption p').html(titleImg);var caption_w=imgW;$('.caption').css({'width':+imgW+'px'});var caption_h=$('.caption').height();$('.all').animate({height:imgH+(caption_h+10)+'px'},300);$('.all').queue(function(){$('.caption').css({'visibility':'visible'}).fadeTo(600,1);$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(300,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});$('.all').dequeue()});}});if($(opt.next_class).is('.next_in')){$('.box_next_in ,.box_previous_in ').css('display','block');$('.box_next,.box_previous ').css('display','none');$(opt.next_class+','+opt.previous_class).css({'visibility':'hidden'});}else{$('.box_next_in, .box_previous_in ').css('display','none');$('.box_next,.box_previous ').css('display','block');$(opt.next_class+','+opt.previous_class).css({'visibility':'hidden'});}
if($('.start ').is('li.end')){$((opt.next_class)).css('visibility','hidden');$('div.box_next_in,div.box_next').css({'display':'none'});$('.end').removeClass('start');$(opt.previous_class).css({'visibility':'visible'});}else{$(opt.next_class+','+opt.previous_class).css({'visibility':'visible'});}
$('.all').dequeue();});}});$(myImg).attr('src',pathImg);return false;});$((opt.previous_class)).bind('click',function(){$('.thumbs_close').css({'opacity':'0','visibility':'hidden'});$('.img_box img').remove('img');$('.pre').css('visibility','visible').show();$('.caption').css({'opacity':'0','visibility':'hidden'});$('.pre').append('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');var pathImg=$('.back>a').attr('href');var titleImg=$('.back>a').attr('title');$((opt.gallery_li)).removeClass('start');$((opt.gallery_li)).queue(function(){$('.back').next('li').addClass('start');$((opt.gallery_li)).dequeue();});$('.back').queue(function(){$((opt.gallery_li)).removeClass('back');$('.start').prev('li').prev('li').addClass('back');$((opt.next_class)).animate({right:'0px'},300);$('.back').dequeue();});$((opt.previous_class)).css('visibility','hidden');$((opt.next_class)).css('visibility','hidden');var myImg=new Image();$(myImg).load(function(){var imgH=myImg.height;var imgW=myImg.width;var w_H=$(window).height();var w_W=$(window).width();$('#'+idPiro+' .img_box').append(this);if(imgH+100>w_H||imgW+100>w_W){var new_img_W=imgW;var new_img_H=imgH;var _x=(imgW+100)/w_W;var _y=(imgH+100)/w_H;if(_y>_x){new_img_W=Math.round(imgW*(0.9/_y));new_img_H=Math.round(imgH*(0.9/_y));}else{new_img_W=Math.round(imgW*(0.9/_x));new_img_H=Math.round(imgH*(0.9/_x));}
imgH+=new_img_H;imgW+=new_img_W;$('.thumbs').show();$('.img_box ').css('visibility','hidden');$('.img_box img').css('visibility','hidden').hide();$('.all').css({'visibility':'visible'}).animate({height:(new_img_H)+'px',width:(new_img_W)+'px',marginLeft:'-'+((new_img_W)/2)+'px',marginTop:'-'+((new_img_H)/2+20)+'px'},(opt.mySpeed));$('.all').queue(function(){$('.img_box').css({visibility:'visible',height:(new_img_H)+'px',width:(new_img_W)+'px'});$('.img_box').queue(function(){$(myImg).height(new_img_H).width(new_img_W).css('opacity',0);$('.img_box img').css('visibility','visible').show().fadeTo(200,1)
$('div.box_next_in,div.box_next').css({'display':'block'});$('.img_box ').addClass('unloader');$('.loader').remove('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');$('.img_box').dequeue()
if(titleImg==""){$('.caption').css('visibility','hidden');$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(300,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});}else{$('.caption p').html(titleImg);var caption_w=new_img_W;$('.caption').css({'width':+new_img_W+'px'});var caption_h=$('.caption').height();$('.all').animate({height:new_img_H+(caption_h+10)+'px'},300);$('.all').queue(function(){$('.caption').css({'visibility':'visible'}).fadeTo(600,1);$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(300,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});$('.all').dequeue()});}});if($(opt.next_class).is('.next_in')){$('.box_next_in ,.box_previous_in ').css('display','block');$('.box_next,.box_previous ').css('display','none');$(opt.next_class+','+opt.previous_class).css({'visibility':'hidden'});}else{$('.box_next_in, .box_previous_in ').css('display','none');$('.box_next,.box_previous ').css('display','block');$(opt.next_class+','+opt.previous_class).css({'visibility':'hidden'});}
if($('.back').is('li.begin')){$((opt.previous_class)).css('visibility','hidden');$((opt.next_class)).css('visibility','visible');$('div.box_previous_in,div.box_previous').css({'display':'none'});$('.begin').removeClass('back');$((opt.gallery_li)).removeClass('start');$((opt.gallery_li)).queue(function(){$('.begin').next('li').next('li').addClass('start');$((opt.gallery_li)).dequeue()});}else{$(opt.next_class+','+opt.previous_class).css('visibility','visible');}
$('.all').dequeue();});}else{$('.thumbs').show();$('.img_box ').css('visibility','hidden');$((opt.next_class)).css('visibility','hidden');$('.img_box img').css('visibility','hidden').hide();$('.all').css({'visibility':'visible'}).animate({height:(imgH)+'px',width:(imgW)+'px',marginLeft:'-'+((imgW)/2)+'px',marginTop:'-'+((imgH)/2+10)+'px'},(opt.mySpeed));$('.all').queue(function(){$('.img_box').css({visibility:'visible',height:(imgH)+'px',width:(imgW)+'px'});$('.img_box').queue(function(){$(myImg).height(imgH).width(imgW).css('opacity',0);$('.img_box img').css('visibility','visible').show().fadeTo(200,1);$('div.box_next_in,div.box_next').css({'display':'block'});$('.img_box ').addClass('unloader');$('.loader').remove('<div class="loader"><span style=" background:'+opt.pathLoader+' "></span></div>');$('.img_box').dequeue()
if(titleImg==""){$('.caption').css('visibility','hidden');$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(300,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});}else{$('.caption p').html(titleImg);var caption_w=imgW;$('.caption').css({'width':+imgW+'px'});var caption_h=$('.caption').height();$('.all').animate({height:imgH+(caption_h+10)+'px'},300);$('.all').queue(function(){$('.caption').css({'visibility':'visible'}).fadeTo(600,1);$('.thumbs_close').show().css({'opacity':'0','visibility':'visible'}).fadeTo(300,1);$('.unloader, .thumbs_close').bind('click',function(){closeIt();});$('.all').dequeue()});}});if($(opt.next_class).is('.next_in')){$('.box_next_in ,.box_previous_in ').css('display','block');$('.box_next,.box_previous ').css('display','none');$(opt.next_class+','+opt.previous_class).css({'visibility':'hidden'});}else{$('.box_next_in, .box_previous_in ').css('display','none');$('.box_next,.box_previous ').css('display','block');$(opt.next_class+','+opt.previous_class).css({'visibility':'hidden'});}
if($('.back').is('li.begin')){$((opt.previous_class)).css('visibility','hidden');$((opt.next_class)).css('visibility','visible');$('div.box_previous_in,div.box_previous').css({'display':'none'});$('.begin').removeClass('back');$((opt.gallery_li)).removeClass('start');$((opt.gallery_li)).queue(function(){$('.begin').next('li').next('li').addClass('start');$((opt.gallery_li)).dequeue()});}else{$(opt.next_class+','+opt.previous_class).css('visibility','visible');}
$('.all').dequeue();});}});$(myImg).attr('src',pathImg);return false;});});}})(jQuery);



/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, 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;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, 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;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, 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;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, 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;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, 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;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		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;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		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;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		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;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) 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;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, 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;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});