//Heavily remixed by Sébastien Mouren

// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// Parts (c) 2005 Justin Palmer (http://encytemedia.com/)
// Parts (c) 2005 Mark Pilgrim (http://diveintomark.org/)
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


var Effect = {};
var Effect2 = Effect; // deprecated

/* ------------- transitions ------------- */

Effect.Transitions = {
	linear: function(pos) {return pos;},

	sinoidal: function(pos) {return (-Math.cos(pos*Math.PI)/2) + 0.5;},

	reverse: function(pos) {return 1-pos;},

	flicker: function(pos) {return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random(0.25);},

	wobble: function(pos) {return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;},

	pulse: function(pos) {return (Math.floor(pos*10) % 2 == 0 ? (pos*10-Math.floor(pos*10)) : 1-(pos*10-Math.floor(pos*10)));},

	none: function(pos) {return 0;},

	full: function(pos) {return 1;}
};

/* ------------- element ext -------------- */

Element.makePositioned = function(element) {
	element = idToObject(element);
	if (element.style.position == "") element.style.position = "relative";
};

Element.makeClipping = function(element) {
	element = idToObject(element);
	element._overflow = element.style.overflow || "visible";
	if(element._overflow!="hidden") element.style.overflow = "hidden";
};

Element.undoClipping = function(element) {
	element = idToObject(element);
	if(element._overflow!="hidden") element.style.overflow = element._overflow;
};

Element.setContentZoom = function(element, percent) {
	element = idToObject(element);
	element.style.fontSize = (percent/100) + "em";
	if(navigator.appVersion.indexOf("AppleWebKit") > 0) window.scrollBy (0,0);
};

Element.getStyle = function(element, style) {
	element = idToObject(element);
	var value = element.style[style.camelize()];
	if(!value) {
		if(document.defaultView && document.defaultView.getComputedStyle) {
			var css = document.defaultView.getComputedStyle(element, null);
			value = (css != null) ? css.getPropertyValue(style) : null;
		} else if(element.currentStyle) value = element.currentStyle[style.camelize()];
	}
	if(value == "auto") value = null;
	return value;
};

String.prototype.camelize = function() {
	var oStringList = this.split("-");
	if(oStringList.length == 1) return oStringList[0];
	var ret = this.indexOf("-") == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0];
	for(var i = 1, len = oStringList.length; i < len; i++){
		var s = oStringList[i];
		ret += s.charAt(0).toUpperCase() + s.substring(1)
	}
	return ret;
};


/* ------------- core effects ------------- */

//Definit une base commune à tous les objets dérivés de la classe Effect
Effect.Base = function() {};
Effect.Base.prototype = {
//Les options par défaut présente dans tous les objets Effect sont initialisées ici
//définit une fonction initialisant les options dans le cadre de l'objet appelant
	setOptions: function(options) {
		this.options = Object.extend({
			transition: Effect.Transitions.sinoidal,//definit la transition employée
			duration: 1.0,// seconds
			fps: 25.0,// max. 100fps
			sync: false, // true for combining
			from: 0.0,//état initial
			to: 1.0//état final
		}, options || {});
//extend option permet lorsque l'on dérive Effect de rajouter de nouvelles options spécifique à l'objet
	},

//définit une fonction des états relatifs au démarrage de l'exécution de l'objet Effect
	start: function(options) {
		this.setOptions(options || {});
		this.currentFrame = 0;// initialise à 0 un compteur d'image accroché à l'objet contextuel
		this.startOn = new Date().getTime();//initialise une constante du temps de démarrage accroché à l'objet contextuel
		this.finishOn = this.startOn + (this.options.duration*1000);//cacule et attribue une constante du temps d'arrêt accrochée à l'objet contextuel
		if(this.options.beforeStart) this.options.beforeStart(this);//appelle la fonction beforeStart si son exécution a été définie dans les options
		if(!this.options.sync) this.loop();//éxucte la fonction loop dans le contexte de l'objet appelant si l'option non synchrone est vrai
	},

//définit une fonction du temps qui contrôle le déroulement de l'animation dans le temps
	loop: function() {
		var timePos = new Date().getTime();//prends un pointeur temporel
//si ce pointeur temporel est au-delà du temps de cloture de l'animation
		if(timePos >= this.finishOn) {
			this.render(1.0);
//effecture le rendu au point final
			if(this.finish) this.finish();
			if(this.options.afterFinish) this.options.afterFinish(this);//S'il existe une option declarée afterFinish, l'exécute
			return;
		}
		var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);//prend un pointeur sur la position en nombre absolu
		var frame = Math.round(pos * this.options.fps * this.options.duration);//calcule la position en nombre d'image
		if(frame > this.currentFrame) {this.render(pos); this.currentFrame = frame;}//conditionne le rendu et la mise à jour du compteur d'image au décalage ente le nombre actuel du compteur et la position en images dans le temps
		this.timeout = setTimeout(this.loop.bind(this), 10);//accroche à la propriété Timeout de l'objet contextuel une fonction qui exécutera de nouveau la fonction toutes les 10ms
	},

//définit une fonction qui effectue le rendu à partir d'un argument de position
	render: function(pos) {
		if(this.options.transition) pos = this.options.transition(pos);//conditionne l'exécution d'une transition avec pour argument la position à la présence d'une option de transition attachée à l'objet appelant
		pos *= (this.options.to-this.options.from);//attribue à l'argument de position sa valeur multipliée par la diffèrence entre l'origine et la destination definis dans les option de l'objet appelant
		pos += this.options.from;//ajoute à l'argument de position, la valeur de l'option de destination de l'objet appelant
		if(this.options.beforeUpdate) this.options.beforeUpdate(this);//conditionne l'exécution d'une option beforeUpdate à son existence auprès de l'objet appelant
		if(this.update) this.update(pos);////conditionne l'exécution d'une fonction update à son existence auprès de l'objet appelant
		if(this.options.afterUpdate) this.options.afterUpdate(this);//conditionne l'exécution d'une option afterUpdate à son existence auprès de l'objet appelant
	},

//définit une fonction d'abandon de la fonction setTimeout positionnée par la fonction de l'option loop
	cancel: function() {if(this.timeout) clearTimeout(this.timeout);}
};

//Assigne à la méthode Parrallel de l'objet Effect la méthode Create() de la l'objet Class
Effect.Parallel = Class.create();
//Assigne la création d'un nouvel objet Effect.Base au prototype de Effect.Parallel et l'étend avec de nouveaux types
Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
//definit l'option initialize. Il s'agit d'une fonction qui
	initialize: function(effects) {
		this.effects = effects || [];
		this.start(arguments[1]);
	},

	update: function(position) {for (var i = 0; i < this.effects.length; i++) this.effects[i].render(position);},

	finish: function(position) {for (var i = 0; i < this.effects.length; i++) if(this.effects[i].finish) this.effects[i].finish(position);}
});

// Internet Explorer caveat: works only on elements that have
// a 'layout', meaning having a given width or height. 
// There is no way to safely set this automatically.
Effect.Opacity = Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
	initialize: function(element) {
		this.element = idToObject(element);
		options = Object.extend({from: 0.0, to: 1.0}, arguments[1] || {});

		this.start(options);
	},

	update: function(position) {this.setOpacity(position);},

	setOpacity: function(opacity) {
		if(opacity == 1.0) {
			this.element.style.opacity = null;
			this.element.style.filter = null;
		} else {
			this.element.style.opacity = opacity;
			this.element.style.filter = "alpha(opacity:"+opacity*100+")";
		}
	}
});

Effect.MoveBy = Class.create();
Object.extend(Object.extend(Effect.MoveBy.prototype, Effect.Base.prototype), {
	initialize: function(element, toTop, toLeft) {
		this.element = idToObject(element);
		this.originalTop = parseFloat(Element.getStyle(element,"top") || "0");
		this.originalLeft = parseFloat(Element.getStyle(element,"left") || "0");
		this.toTop = toTop;
		this.toLeft = toLeft;
		Element.makePositioned(this.element);
		this.start(arguments[3]);
	},

	update: function(position) {
		var topd = this.toTop * position + this.originalTop;
		var leftd = this.toLeft * position + this.originalLeft;
		this.setPosition(topd, leftd);
	},

	setPosition: function(topd, leftd) {
		this.element.style.top = topd + "px";
		this.element.style.left = leftd + "px";
	}
});

Effect.Scale = Class.create();
Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
	initialize: function(element, percent) {
		this.element = idToObject(element),
//scale mode take 'box' or 'contents' or {} with provided values as input
		options = Object.extend({scaleX: true, scaleY: true, scaleContent: true, scaleFromCenter: false, scaleMode: "box", scaleFrom: 100.0}, arguments[2] || {});
		this.originalTop = this.element.offsetTop;
		this.originalLeft = this.element.offsetLeft;
		if(Element.getStyle(element, "font-size") == "") this.sizeEm = 1.0;
		if(Element.getStyle(element, "font-size") && Element.getStyle(element, "font-size").indexOf("em") > 0) this.sizeEm = parseFloat(Element.getStyle(element,"font-size"));
		this.factor = (percent / 100.0) - (options.scaleFrom / 100.0);
		if(options.scaleMode == "box") {
			this.originalHeight = this.element.clientHeight;
			this.originalWidth = this.element.clientWidth; 
		} else if(options.scaleMode == "contents") {
			this.originalHeight = this.element.scrollHeight;
			this.originalWidth = this.element.scrollWidth;
		} else {
			this.originalHeight = options.scaleMode.originalHeight;
			this.originalWidth = options.scaleMode.originalWidth;
		}
		this.start(options);
	},

	update: function(position) {
		var currentScale = (this.options.scaleFrom / 100.0) + (this.factor * position);
		if(this.options.scaleContent && this.sizeEm) this.element.style.fontSize = this.sizeEm * currentScale + "em";
		this.setDimensions(this.originalWidth * currentScale, this.originalHeight * currentScale);
	},

	setDimensions: function(width, height) {
		if(this.options.scaleX) this.element.style.width = width + "px";
		if(this.options.scaleY) this.element.style.height = height + "px";
		if(this.options.scaleFromCenter) {
			var topd = (height - this.originalHeight)/2;
			var leftd = (width - this.originalWidth)/2;
			if(Element.getStyle(this.element, "position") == "absolute") {
				if(this.options.scaleY) this.element.style.top = this.originalTop-topd + "px";
				if(this.options.scaleX) this.element.style.left = this.originalLeft-leftd + "px";
			} else {
				if(this.options.scaleY) this.element.style.top = -topd + "px";
				if(this.options.scaleX) this.element.style.left = -leftd + "px";
			}
		}
	}
});

Effect.Highlight = Class.create();
Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
	initialize: function(element) {
		this.element = idToObject(element);
// try to parse current background color as default for endcolor
// browser stores this as: "rgb(255, 255, 255)", convert to "#ffffff" format
		var endcolor = "#ffffff";
		var current = Element.getStyle(this.element, "background-color");
		if(current && current.slice(0,4) == "rgb(") {
			endcolor = "#";
			var cols = current.slice(4,current.length-1).split(",");
			var i=0; do {endcolor += parseInt(cols[i]).toColorPart()} while (++i<3);
		}
		var options = Object.extend({startcolor: "#ffff99", endcolor: endcolor,restorecolor: current}, arguments[1] || {});
// init color calculations
		this.colors_base = [
			parseInt(options.startcolor.slice(1,3),16),
			parseInt(options.startcolor.slice(3,5),16),
			parseInt(options.startcolor.slice(5),16)
		];
		this.colors_delta = [
			parseInt(options.endcolor.slice(1,3),16)-this.colors_base[0],
			parseInt(options.endcolor.slice(3,5),16)-this.colors_base[1],
			parseInt(options.endcolor.slice(5),16)-this.colors_base[2]
		];
		this.start(options);
	},

	update: function(position) {
		var colors = [
			Math.round(this.colors_base[0]+(this.colors_delta[0]*position)),
			Math.round(this.colors_base[1]+(this.colors_delta[1]*position)),
			Math.round(this.colors_base[2]+(this.colors_delta[2]*position))
		];
		this.element.style.backgroundColor = "#" + colors[0].toColorPart() + colors[1].toColorPart() + colors[2].toColorPart();
	},

	finish: function() {
		this.element.style.backgroundColor = this.options.restorecolor;
	}
});

Effect.ScrollTo = Class.create();
Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
	initialize: function(element) {
		this.element = idToObject(element);
		Position.prepare();
		var offsets = Position.cumulativeOffset(this.element);
		var max = window.innerHeight ? window.height - window.innerHeight : document.body.scrollHeight - (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight);
		this.scrollStart = Position.deltaY;
		this.delta  = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
		this.start(arguments[1] || {});
	},

	update: function(position) {
		Position.prepare();
		window.scrollTo(Position.deltaX, this.scrollStart + (position*this.delta));
	}
});


/* ------------- prepackaged effects ------------- */

Effect.Fade = function(element) {
	options = Object.extend({
		from: 1.0,
		to: 0.0,
		afterFinish: function(effect) 
		{
		Element.hide(effect.element);
		effect.setOpacity(1); } 
	}, arguments[1] || {});
	return new Effect.Opacity(element,options);
};

Effect.Appear = function(element) {
	options = Object.extend({
		from: 0.0,
		to: 1.0,
		beforeStart: function(effect) {
			effect.setOpacity(0);
			Element.show(effect.element);
			},
		afterUpdate: function(effect) {Element.show(effect.element);}
	}, arguments[1] || {});
	return new Effect.Opacity(element,options);
};

Effect.Puff = function(element) {
	return new Effect.Parallel([
			new Effect.Scale(element, 200, {sync: true, scaleFromCenter: true, scaleMode: "box"}), 
			new Effect.Opacity(element, {sync: true, to: 0, from: 1.0})
		], {
			duration: 0.6,
			fps: 30,
			beforeUpdate: function(effect) {
				effect.effects[0].element.style.zindex = "1001";
				effect.effects[0].element.style.position = "absolute";
			}//,
			//afterFinish: function(effect) {Element.hide(effect.effects[0].element);}
		}
	);
};

Effect.BlindUp = function(element) {
	Element.makeClipping(element);
	return new Effect.Scale(
		element,
		0,
		Object.extend({
			scaleContent: false, 
			scaleX: false, 
			afterFinish: function(effect)
			{
				Element.hide(effect.element);
				Element.undoClipping(effect.element);
			}
		}, arguments[1] || {})
	);
};

Effect.BlindDown = function(element) {
	idToObject(element).style.height = "0px";
	Element.makeClipping(element);
	Element.show(element);
	return new Effect.Scale(
		element,
		100, 
		Object.extend({
			scaleContent: false, 
			scaleX: false, 
			scaleMode: "contents",
			scaleFrom: 0,
			afterFinish: function(effect) {Element.undoClipping(effect.element);}
		}, arguments[1] || {})
	);
};

Effect.SwitchOff = function(element) {
	return new Effect.Appear(
		element,
		{
			duration: 0.4,
			transition: Effect.Transitions.flicker,
			afterFinish: function(effect) {
				effect.element.style.overflow = "hidden";
				new Effect.Scale(
					effect.element,
					1,
					{
						duration: 0.3,
						scaleFromCenter: true,
						scaleX: false,
						scaleContent: false,
						afterUpdate: function(effect) {Element.makePositioned(this.element);},
						afterFinish: function(effect) {Element.hide(effect.element);}
					}
				)
			}
		}
	);
};

Effect.DropOut = function(element) {
	return new Effect.Parallel([
			new Effect.MoveBy(element, 100, 0, { sync: true }),
			new Effect.Opacity(
				element,
				{
					sync: true,
					to: 0.0,
					from: 1.0
				}
			)
		],
		{
			duration: 0.5,
			afterFinish: function(effect) {Element.hide(effect.effects[0].element);}
		}
	);
};

Effect.Shake = function(element) {
	return new Effect.MoveBy(
		element,
		0,
		20,
		{
			duration: 0.05,
			afterFinish: function(effect) {
				new Effect.MoveBy(
					effect.element,
					0,
					-40,
					{
						duration: 0.1,
						afterFinish: function(effect) {
							new Effect.MoveBy(
								effect.element,
								0,
								40,
								{
									duration: 0.1,
									afterFinish: function(effect) {
										new Effect.MoveBy(
											effect.element,
											0,
											-40,
											{
												duration: 0.1,
												afterFinish: function(effect) {
													new Effect.MoveBy(
														effect.element,
														0,
														40,
														{
															duration: 0.1,
															afterFinish: function(effect) {
																new Effect.MoveBy(
																	effect.element,
																	0,
																	-20,
																	{
																		duration: 0.05,
																		afterFinish: function(effect) {}
																	}
																)
															}
														}
													)
												}
											}
										)
									}
								}
							)
						}
					}
				)
			}
		}
	);
};

Effect.SlideDown = function(objElement) {
	objElement = idToObject(objElement);
	objElement.style.height = "0px";
	Element.makeClipping(objElement);
	Element.cleanWhitespace(objElement);
	Element.makePositioned(objElement.firstChild);
	Element.show(objElement);
	return new Effect.Scale(
		objElement,
		100,
		Object.extend({
			scaleContent: false,
			scaleX: false,
			scaleMode: "contents",
			scaleFrom: 0,
			afterUpdate: function(effect) {effect.element.firstChild.style.bottom = (effect.originalHeight - effect.element.clientHeight) + "px";},
			afterFinish: function(effect) {Element.undoClipping(effect.element);}
		}, arguments[1] || {})
	);
};

Effect.SlideUp = function(objElement) {
	objElement = idToObject(objElement);
	Element.makeClipping(objElement);
	Element.cleanWhitespace(objElement);
	Element.makePositioned(objElement.firstChild);
	Element.show(objElement);
	return new Effect.Scale(
		objElement,
		0, 
		Object.extend({
			scaleContent: false,
			scaleX: false,
//			scaleMode: "contents",
			afterUpdate: function(effect) {effect.element.firstChild.style.bottom = (effect.originalHeight - effect.element.clientHeight) + "px";},
			afterFinish: function(effect)
			{
				Element.hide(effect.element);
				Element.undoClipping(effect.element);
			}
		}, arguments[1] || {})
	);
};

Effect.Squish = function(element) {
	return new Effect.Scale(
		element,
		0,
		{afterFinish: function(effect) {Element.hide(effect.element);}}
	);
};

Effect.Grow = function(objElement) {
	objElement = idToObject(objElement);
	var objOptions = arguments[1] || {};
	var nScaleTo = objOptions.scaleTo || 100;
	var nScaleFrom = objOptions.scaleFrom || 0;
	var nOriginalWidth = objElement.clientWidth;
	var nOriginalHeight = objElement.clientHeight;
	var strDirection = objOptions.direction || "center";
	var fMoveTransition = objOptions.moveTransition || Effect.Transitions.sinoidal;
	var fScaleTransition = objOptions.fScaleTransition || Effect.Transitions.sinoidal;
	var fOpacityTransition = objOptions.fOpacityTransition || Effect.Transitions.full;
	var nInitialMoveX, nInitialMoveY;
	var nMoveX, nMoveY;
	objElement.style.overflow = "hidden";
	Element.show(objElement);
	switch (strDirection) {
		case "top-left":
			nInitialMoveX = nInitialMoveY = nMoveX = nMoveY = 0; 
			break;
		case "top-right":
			nInitialMoveX = nOriginalWidth;
			nInitialMoveY = nMoveY = 0;
			nMoveX = -nOriginalWidth;
			break;
		case "bottom-left":
			nInitialMoveX = nMoveX = 0;
			nInitialMoveY = nOriginalHeight;
			nMoveY = -nOriginalHeight;
			break;
		case "bottom-right":
			nInitialMoveX = nOriginalWidth;
			nInitialMoveY = nOriginalHeight;
			nMoveX = -nOriginalWidth;
			nMoveY = -nOriginalHeight;
			break;
		case "center":
			nInitialMoveX = nOriginalWidth / 2;
			nInitialMoveY = nOriginalHeight / 2;
			nMoveX = -nOriginalWidth / 2;
			nMoveY = -nOriginalHeight / 2;
			break;
	}
	return new Effect.Parallel([
		new Effect.Opacity(objElement, {sync: true, to: 1.0, from: 0.0, transition: fOpacityTransition}),
//		new Effect.MoveBy(objElement, nMoveY, nMoveX, {sync: true, transition: fMoveTransition}),
		new Effect.Scale(objElement, nScaleTo, {scaleMode: {originalHeight: nOriginalHeight, originalWidth: nOriginalWidth}, sync: true, scaleFrom: nScaleFrom, transition: fScaleTransition})
	], objOptions);
};

Effect.Shrink = function(objElement) {
	objElement = idToObject(objElement);
	var objOptions = arguments[1] || {};
	var nOriginalWidth = objElement.clientWidth;
	var nOriginalHeight = objElement.clientHeight;
	var nScaleTo = objOptions.scaleTo || 100;
	var nScaleFrom = objOptions.scaleFrom || 0;
	objElement.style.overflow = "hidden";
	Element.show(objElement);
	var strDirection = objOptions.direction || "center";
	var fMoveTransition = objOptions.fMoveTransition || Effect.Transitions.sinoidal;
	var fScaleTransition = objOptions.fScaleTransition || Effect.Transitions.sinoidal;
	var fOpacityTransition = objOptions.fOpacityTransition || Effect.Transitions.none;
	var nMoveX, nMoveY;
	switch (strDirection) {
		case "top-left":
			nMoveX = nMoveY = 0;
			break;
		case "top-right":
			nMoveX = nOriginalWidth;
			nMoveY = 0;
			break;
		case "bottom-left":
			nMoveX = 0;
			nMoveY = nOriginalHeight;
			break;
		case "bottom-right":
			nMoveX = nOriginalWidth;
			nMoveY = nOriginalHeight;
			break;
		case "center":  
			nMoveX = nOriginalWidth / 2;
			nMoveY = nOriginalHeight / 2;
			break;
	}
	return new Effect.Parallel([
		new Effect.Opacity(objElement, {sync: true, to: 0.0, from: 1.0, transition: fOpacityTransition}),
		new Effect.Scale(objElement, nScaleTo, {sync: true, scaleFrom: nScaleFrom, transition: fMoveTransition}),
//		new Effect.MoveBy(objElement, nMoveY, nMoveX, {sync: true, transition: fScaleTransition})
	],
	objOptions);
};

Effect.Pulsate = function(element) {
	var options = arguments[1] || {};
	var transition = options.transition || Effect.Transitions.sinoidal;
	var reverser = function(pos) {return transition(1-Effect.Transitions.pulse(pos))};
	reverser.bind(transition);
	return new Effect.Opacity(
		element,
		Object.extend(Object.extend({
			duration: 3.0,
			afterFinish: function(effect) {Element.show(effect.element);}
		}, options), {transition: reverser})
	);
};

Effect.Fold = function(element) {
	idToObject(element).style.overflow = "hidden";
	return new Effect.Scale(
		element,
		5,
		Object.extend({
			scaleContent: false,
			scaleTo: 100,
			scaleX: false,
			afterFinish: function(effect) {
				new Effect.Scale(
					element,
					1, {
						scaleContent: false,
						scaleTo: 0,
						scaleY: false,
						afterFinish: function(effect) {Element.hide(effect.element)}
					}
				);
			}
		}, arguments[1] || {})
	);
};

Effect.SlideRightIntoView = function(objElement) {
	objElement = idToObject(objElement);
	objElement.style.width = "0px";
	objElement.style.overflow = "hidden";
	objElement.firstChild.style.position = "relative";
	Element.show(objElement);
	new Effect.Scale(
		objElement,
		100, {
			scaleContent: false,
			scaleY: false,
			scaleMode: "contents",
			scaleFrom: 0,
			afterUpdate: function(effect) {effect.objElement.firstChild.style.width = (effect.originalWidth - effect.objElement.clientWidth) + "px";}
		}.extend(arguments[1] || {})
	);
}

Effect.SlideRightOutOfView = function(objElement) {
	objElement = idToObject(objElement);
	objElement.style.overflow = "hidden";
	objElement.firstChild.style.position = "relative";
	Element.show(objElement);
	new Effect.Scale(
		objElement,
		0, {
			scaleContent: false,
			scaleY: false,
			afterUpdate: function(effect) {effect.objElement.firstChild.style.width = (effect.originalWidth - effect.objElement.clientWidth) + "px";},
			afterFinish: function(effect) {Element.hide(effect.objElement);}
		}.extend(arguments[1] || {})
	);
}