/*** be nice - don't steal - design and implementation: copyright 2005 atelierfabien.be ***/

/*** transitions ***/

Effect.Transitions.cosinoidal = function(pos) {	
	return 0.5 * (Math.cos(Math.PI * (1 + pos)) + 1);
}

Effect.Transitions.smooth = function(pos) {	
	return 1 - Math.abs(Math.pow(pos-1, 3));
}

Effect.Transitions.ultrasmooth = function(pos) {
	pos = Effect.Transitions.sinoidal(pos);
	return 1 - Math.abs(Math.pow(pos-1, 3));
}

Effect.Transitions.accelerate = function(pos) {
	pos = Math.pow(pos, 3);
	return 1 - Math.abs(Math.pow(pos-1, 3));
}

Effect.Transitions.binary = function(pos) {
	return Math.round(pos);
}

Effect.Transitions.steps = function(pos) {
	return Math.round(pos / 0.25) * 0.25;
}

Effect.Transitions.exponential = function(pos) {
	return 1 - Math.pow(1-pos, 2);
}

Effect.Transitions.slowstop = function(pos) {
	return 1-Math.pow(0.5, 20*pos);
}

/*** special precalculated transitions see: http://laco.wz.cz/tween/?page=customeasing ***/

Effect.Transitions.Presets = {}

Effect.Transitions.Presets.easeOutBounce = function(pos) {
	var preset = [0,0.0082,0.0328,0.0741,0.1325,0.208,0.301,0.4119,0.5407,0.6879,0.8537,0.9829,0.9064,0.8449,0.7987,0.7682,0.7537,0.7556,0.7742,0.81,0.8633,0.9345,0.989,0.9557,0.9394,0.9396,0.9558,0.9875,0.9904,1];
	var p = (Math.ceil(pos * (preset.length - 1)));
	return preset[p];
}

Effect.Transitions.Presets.easeOutBack = function(pos) {
	var preset = [0,0.1464,0.2805,0.4026,0.5133,0.6128,0.7016,0.7801,0.8485,0.9072,0.9565,0.9967,1.0295,1.0546,1.0723,1.0842,1.0915,1.095,1.0952,1.0927,1.0877,1.0807,1.0717,1.0597,1.0457,1.0334,1.0228,1.0141,1.0073,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

Effect.Transitions.Presets.easeInOutBack = function(pos) {
	var preset = [0,-0.0056,-0.0194,-0.0388,-0.0618,-0.0794,-0.0918,-0.0973,-0.0938,-0.0775,-0.0409,0.017,0.0933,0.1993,0.3348,0.5,0.6716,0.8062,0.9082,0.9831,1.0433,1.0771,1.0935,1.0974,1.0918,1.0784,1.0576,1.0374,1.0195,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	if(p == preset.length) { return 1.0; }
	return preset[p];
}

Effect.Transitions.Presets.easeOutElastic = function(pos) {
	var preset = [0,0.4325,0.857,1.275,1.3718,1.2957,1.1017,0.9571,0.8825,0.8703,0.9141,0.9916,1.029,1.0413,1.0363,1.0186,0.9962,0.9836,0.981,0.9879,1.0014,1.006,1.0075,1.0064,1.003,0.9994,0.9982,0.9976,0.9976,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

Effect.Transitions.Presets.easeInExpoSmooth = function(pos) {
	var preset = [0,-0.0005,-0.0007,-0.0006,-0.0002,0.0005,0.0015,0.0029,0.0046,0.0067,0.0092,0.0122,0.0156,0.0195,0.0238,0.0324,0.0444,0.0592,0.0775,0.1,0.1282,0.164,0.2112,0.2783,0.3986,0.5885,0.7354,0.8455,0.9237,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

Effect.Transitions.Presets.easeInOutExpo = function(pos) {
	var preset = [0,-0.0011,-0.0014,-0.001,0.0003,0.0026,0.0063,0.0116,0.0189,0.0291,0.0435,0.0729,0.1228,0.1973,0.3104,0.5,0.6859,0.8032,0.8783,0.9245,0.9504,0.9667,0.9779,0.986,0.9918,0.9959,0.9986,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

Effect.Transitions.Presets.easeInExpo = function(pos) {
	var preset =  [0,-0.0005,-0.0007,-0.0006,-0.0002,0.0005,0.0015,0.0029,0.0046,0.0067,0.0092,0.0122,0.0156,0.0195,0.0238,0.0295,0.0375,0.048,0.0615,0.0783,0.0992,0.125,0.157,0.197,0.2481,0.316,0.4011,0.5044,0.6317,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

Effect.Transitions.Presets.easeOutExpo = function(pos) {
	var preset =  [0,0.2007,0.3657,0.499,0.604,0.6838,0.7499,0.8016,0.8427,0.8756,0.9019,0.9226,0.9387,0.9507,0.9593,0.9665,0.9725,0.9775,0.9817,0.9853,0.9883,0.9909,0.9931,0.9949,0.9964,0.9975,0.9985,0.9992,0.9996,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

Effect.Transitions.Presets.easeInOutFloat = function(pos) {
	var preset = [0,-0.1387,-0.2503,-0.3355,-0.3948,-0.429,-0.4385,-0.4241,-0.3862,-0.3253,-0.242,-0.1368,-0.0101,0.1404,0.2913,0.4293,0.5546,0.6672,0.7671,0.8544,0.9292,0.9915,1.0413,1.0788,1.104,1.117,1.1177,1.1063,1.0829,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

Effect.Transitions.Presets.easeOutTwoStep = function(pos) {
	var preset = [0,0.0999,0.1801,0.2467,0.3031,0.3515,0.3935,0.4301,0.4622,0.4903,0.515,0.5367,0.5556,0.5721,0.5864,0.5987,0.6091,0.6178,0.625,0.6421,0.7386,0.8034,0.8513,0.8883,0.9174,0.9407,0.9592,0.9738,0.9852,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

Effect.Transitions.Presets.easeLaunch = function(pos) {
	var preset =  [0,0.0233,0.0501,0.0809,0.1164,0.1577,0.2061,0.2634,0.3328,0.4196,0.5347,0.7103,1.0053,1.0259,1.044,1.0598,1.0731,1.0841,1.0925,1.0986,1.1021,1.1032,1.1019,1.098,1.0916,1.0827,1.0713,1.0573,1.0408,1];
	var p = (Math.ceil(pos * (preset.length - 1))); 
	return preset[p];
}

/*** simple effects ***/

Effect.BlindToggle = function(element) {
	$(element).style.display == 'none'
	? Object.extend(new Effect.BlindDown(element), arguments[1] || {})
	: Object.extend(new Effect.BlindUp(element), arguments[1] || {})
}

Effect.SlideToggle = function(element) {
	$(element).style.display == 'none'
	? Object.extend(new Effect.SlideDown(element), arguments[1] || {})
	: Object.extend(new Effect.SlideUp(element), arguments[1] || {})
}

Effect.StageBase = function(element, amount) {
	new Effect.MoveBy(element, 0, amount,
		{ duration: 0.05, afterFinish: function(effect) {
	new Effect.MoveBy(effect.element, 0, -(amount*2),
		{ duration: 0.05, afterFinish: function(effect) {
	new Effect.MoveBy(effect.element, 0, amount < 0 ? -1000 : 1000,
		{ duration: 0.5, afterFinish: function(effect) {
	new Element.hide(element);
	}}) }}) }});
}

Effect.StageLeft = function(element) {
	new Effect.StageBase(element, -20)
}

Effect.StageRight = function(element) {
	new Effect.StageBase(element, 20)
}

Effect.Pause = Class.create();
Object.extend(Object.extend(Effect.Pause.prototype, Effect.Base.prototype), {
	
	// dummy class to pause and attach afterFinish callback
	
	initialize: function(reference) {
		this.reference = (reference ||  {});
		this.start(arguments[1]);
	}

});

Effect.Expand = function(element) {
	return new Effect.Scale(element, 0, { 
		transition: Effect.Transitions.reverse
	});
}

Effect.MoveTo = Class.create();
Object.extend(Object.extend(Effect.MoveTo.prototype, Effect.Move.prototype), {
	initialize: function(element, toTop, toLeft) {
		this.element = $(element);
		var options = Object.extend({	x: toLeft, y: toTop, mode: 'absolute' }, arguments[3] || {});
		this.start(options);
	}
});

Effect.Minimize = function(element, section) {				
	var element = $(element);
	var options = (arguments[2] || {});	
	if(!section) { Element.cleanWhitespace(element); section = element.firstChild; }	
	new Effect.ResizeTo(element, 0, 0, 
		Object.extend({			
			transition: (options.transition || Effect.Transitions.sinoidal),
			afterFinish: function(effect) { Element.hide(section); }
		}, options));
}

Effect.Maximize = function(element, section) {				
	var element = $(element);
	var options = (arguments[2] || {});	
	if(!section) { Element.cleanWhitespace(element); section = element.firstChild; }	
	Element.show(section);	
	new Effect.ResizeTo(element, section.clientWidth, section.clientHeight,
		Object.extend({			
			transition: (options.transition || Effect.Transitions.sinoidal)					
		}, options));
}

Effect.MinimizeLeft = function(element, container, toWidth, toHeight) {				
	var element = $(element);
	var container = $(container);
	var options = (arguments[4] || {duration: 1.0});
	
	var doResizeX, doResizeY;
	
	if(options.reverse) { 
		doResizeX = false;
		doResizeY = true;
	} else {
		doResizeX = true;
		doResizeY = false;
	}
	
	new Effect.ResizeTo(container, toWidth, toHeight, {
		resizeX: doResizeX, resizeY: doResizeY,				
		transition: (options.transition || Effect.Transitions.sinoidal),
		duration: (options.duration / 2),
		afterFinish: function(effect) {
			new Effect.ResizeTo(effect.element, toWidth, toHeight, 
				Object.extend({
					resizeX: doResizeY, resizeY: doResizeX,					
					transition: (options.transition || Effect.Transitions.sinoidal),	
					duration: (options.duration / 2)
				}, {afterFinish: options.afterFinish})
			)}
		});
}

Effect.PushLeft = function(element, container) {				
	var element = $(element);
	var container = $(container);
	var options = (arguments[2] || {duration: 1.0});
	
	if(options.reverse) { 
		var dir = -1; 
	} else { 
		Element.show(element);
		var dir = 1;
	}
	
	new Effect.ResizeTo(container, element.clientWidth, element.clientHeight, Object.extend({
		resizeX: true, resizeY: true,				
		transition: (options.transition || Effect.Transitions.sinoidal),
		duration: (options.duration / 2),
		afterFinish: function(effect) {
				if(options.reverse) {
					var fin = function(effect) { Element.hide(element); }
				} else {
					var fin = null;
				}
				new Effect.MoveBy(element, 0, dir * element.clientWidth, {
					duration: (options.duration / 2),
					afterFinish: fin
				});							
			}						
		}, options));
}

Effect.PushTop = function(element, container, toWidth, toHeight) {				
	var element = $(element);
	var container = $(container);
	var options = (arguments[4] || {duration: 1.0});
	
	if(options.reverse) { 
		var dir = 1; 
		var hide = function(effect) { Element.hide(element); }
	} else { 
		var dir = -1;									
		var hide = null;					
	}
	
	new Effect.ResizeTo(container, toWidth, toHeight, Object.extend({
		resizeX: true, resizeY: true,	resizeFromCenter: true,			
		transition: (options.transition || Effect.Transitions.sinoidal),
		duration: (options.duration / 2),
		afterFinish: function(effect) {		
				if(!options.back) { Element.show(element); }
				new Effect.MoveBy(element, dir * toHeight, 0, {
					duration: (options.duration / 2),
					transition: effect.options.transition,
					afterFinish: hide
				});
			}						
		}, options));				
}

Effect.DropIn = function(element) {
	element = $(element);
	var oldTop = element.style.top;
	var oldLeft = element.style.left;
	var pos = Position.cumulativeOffset(element);
	return new Effect.Parallel([ 
		new Effect.MoveBy(element, 100, 0, { sync: true }), 
		new Effect.Opacity(element, { sync: true, from:0.0, to: 1.0 }) ],
		Object.extend({ 
			duration: 0.5,
			beforeSetup: function(effect) { 
			Element.makePositioned(effect.effects[0].element); 
			Element.setOpacity(element, 0);
			element.style.position = 'absolute'; 
			element.style.top = (pos[1]-100) + 'px'; 
		}
	}, arguments[1] || {}));
}

Effect.MoveAndResizeTo = Class.create();
Object.extend(Object.extend(Effect.MoveAndResizeTo.prototype, Effect.Base.prototype), {
	
	initialize: function(element, toTop, toLeft, toWidth, toHeight) {
		this.element      = $(element);
		this.toTop        = toTop;
		this.toLeft       = toLeft;
		this.toWidth      = toWidth;
		this.toHeight     = toHeight;
		this.start(arguments[5]);
	},
	
	setup: function() {	
		this.originalTop  = parseFloat(Element.getStyle(this.element,'top')  || '0');
		this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0');
		this.originalWidth  = parseFloat(Element.getStyle(this.element,'width')  || '0');
		this.originalHeight = parseFloat(Element.getStyle(this.element,'height') || '0');
		
		// must be absolutely positioned. or else you dont know what this will do!
		Element.makePositioned(this.element);
		this.element.style.position = 'absolute';
	},
	
	update: function(position) {	
		topd  = this.toTop * (position) + this.originalTop * (1 - position);
		leftd = this.toLeft * (position) + this.originalLeft * (1 - position);
		widthd  = this.toWidth * (position) + this.originalWidth * (1 - position);
		heightd = this.toHeight * (position) + this.originalHeight * (1 - position);
		this.setPosition(topd, leftd, widthd, heightd);
	},
	
	setPosition: function(topd, leftd, widthd, heightd) {	
		this.element.style.top = topd+'px';
		this.element.style.left = leftd+'px';
		this.element.style.width = widthd+'px';
		this.element.style.height = heightd+'px';
	}

});

/*** disable selection on elements ***/

Element.disableSelection = function(elem, bool) {
	$(elem).selectDisabled = !bool; // set bool true to disable
}

Effect.disableSelectionByClassName = function(className) {
	document.disabledTextSelectionClassName = (className || 'select-disabled');
	if(/MSIE/.test(navigator.userAgent)) {
		document.onselectstart = function(event) {
			if(Element.Class.has(Event.element(event), document.disabledTextSelectionClassName)
				|| Event.element(event).selectDisabled) {
				return false;
			}
		};
	} else { // assume DOM
		document.onmousedown = function(event) {
			if(Element.Class.has(Event.element(event), document.disabledTextSelectionClassName)
				|| Event.element(event).selectDisabled) {
				return false;
			}
		};
	}
}

Effect.disableSelectionByTags = function(excludeTags) {
	if(!excludeTags) { excludeTags = 'input|textarea'; }
	var regex = new RegExp(excludeTags, 'i');
	
	if(/MSIE/.test(navigator.userAgent)) {
		document.onselectstart = function(event) {
			if(!regex.test(Event.element(event).tagName)
				|| Event.element(event).selectDisabled) {
				return false;
			}
		};
	} else { // assume DOM
		document.onmousedown = function(event) {
			if(!regex.test(Event.element(event).tagName)
				|| Event.element(event).selectDisabled) {
				return false;
			}
		};
	}
}

Element.wrapChildren = function(elem, htmlelem) {
	var element = $(elem);
	if(element) {
		var tempNode = Builder.node('div');
		var newNode = Builder.node(htmlelem, arguments[2] || null);
		tempNode.appendChild(newNode);
		newNode.innerHTML = element.innerHTML;
		element.innerHTML = tempNode.innerHTML;
	}
	return element;
}

Element.wrapElement = function(elem, htmlelem) {
	var element = $(elem);
	if(element) {
		var newNode = Builder.node(htmlelem, arguments[2]);			
		element.parentNode.replaceChild(newNode, element);
		newNode.appendChild(element);
		return newNode;
	}
	return element;
}

/*** combined effects ***/

Effect.ResizeTo = Class.create();
Object.extend(Object.extend(Effect.ResizeTo.prototype, Effect.Base.prototype), {
	
	/***
	
	- description: resize to a defined size (in px)
	
	***/

	initialize: function() {
		this.element = $(arguments[0] || document.rootElement);
		
		this.originalWidth  = this.element.clientWidth; 
		this.originalHeight = this.element.clientHeight;
			
		if(!Var.is_null(arguments[1])) {
			this.newWidth = arguments[1];
		} else {
			this.newWidth = this.originalWidth;
		}
		
		if(!Var.is_null(arguments[2])) {
			this.newHeight = arguments[2];
		} else {
			this.newHeight = this.originalHeight;
		}
		
		this.deltaWidth = this.newWidth - this.originalWidth;
		this.deltaHeight = this.newHeight - this.originalHeight;
		
		var options = Object.extend({
			from: 0.0,
			to:   1.0,
			resizeX: true,
			resizeY: true,
			resizeFromCenter: false
		}, arguments[3] || {});
		
		Element.Class.add(this.element, 'busy'); 
		
		this.start(options);	
	},
	
	update: function(position) {
		var w = this.originalWidth + (position * this.deltaWidth);
		var h = this.originalHeight + (position * this.deltaHeight);
		w = (w >= 0) ? w : 0; 
		h = (h >= 0) ? h : 0; 
		this.setDimensions(Math.round(w), Math.round(h));
	}, 
	
	setDimensions: function(width, height) {
		if(this.options.resizeX) this.element.style.width = width + 'px';
		if(this.options.resizeY) this.element.style.height = height + 'px';
		if(this.options.resizeFromCenter) {
			topd  = (height - this.originalHeight)/2;
			leftd = (width  - this.originalWidth)/2;
			if(this.element.style.position=='absolute') {
				if(this.options.resizeY) this.element.style.top = this.originalTop-topd + 'px';
				if(this.options.resizeX) this.element.style.left = this.originalLeft-leftd + 'px';
			} else {
				if(this.options.resizeY) this.element.style.top = -topd + 'px';
				if(this.options.resizeX) this.element.style.left = -leftd + 'px';
			}
		}		
	},
	
	finish: function() {
		setTimeout(this.ready.bind(this), (this.options.duration*500));
	},
	
	ready: function() {
		if(this.options['after_ready']) { this.options['after_ready'](this); }
		Element.Class.remove(this.element, 'busy');
	}
});

Effect.toggleHeight = function(elem, minHeight, duration) {
	if(!Element.Class.has(elem, 'busy')) {
		var wrapper = $(elem);
		Element.cleanWhitespace(wrapper);
		var contentWrapper = wrapper.firstChild;
		if(contentWrapper) {
			Element.makePositioned(contentWrapper);	
			var minHeight = (minHeight || 0);
			var maxHeight = contentWrapper.clientHeight;			
			var duration = (duration || 1.0);
			if(!Element.Class.has('switch', 'open')) {								
				new Effect.ResizeTo(elem, null, maxHeight, {duration: duration, resizeX: false,
					transition: Effect.Transitions.smooth,
					afterUpdate: function(effect) {
						contentWrapper.style.bottom = (effect.newHeight - effect.element.clientHeight) + 'px';
					},
					afterFinish: function(effect) {
						Element.Class.add('switch', 'open');
					}});
			} else {
				new Effect.ResizeTo(elem, null, minHeight, {duration: duration, resizeX: false,
					transition: Effect.Transitions.smooth,
					afterUpdate: function(effect) {
						contentWrapper.style.bottom = (effect.originalHeight - effect.element.clientHeight) + 'px';
					},
					afterFinish: function(effect) {
						Element.Class.remove('switch', 'open');
					}});
			}
		}
	}
	return false;
}

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

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

Effect.MoveFromBottom = Class.create();
Object.extend(Object.extend(Effect.MoveFromBottom.prototype, Effect.Base.prototype), {
	initialize: function(element) {
		this.element = $(element);
			var options = Object.extend({
				x:    0,
				y:    0,
				mode: 'relative'
		}, arguments[1] || {});
		this.start(options);
	},
	setup: function() {
		Element.makePositioned(this.element);
		this.originalLeft = parseFloat(Element.getStyle(this.element,'left') || '0');
		this.originalBottom  = parseFloat(Element.getStyle(this.element,'bottom')  || '0');
		if(this.options.mode == 'absolute') {
			// absolute movement, so we need to calc deltaX and deltaY
			this.options.x = this.options.x - this.originalLeft;
			this.options.y = this.options.y - this.originalBottom;
		}
	},
	update: function(position) {
		Element.setStyle(this.element, {
			left: Math.round(this.options.x  * position + this.originalLeft) + 'px',
			bottom: Math.round(this.options.y  * position + this.originalBottom)  + 'px'
		});
  	}
});

Effect.BottomPane = Class.create();
Effect.BottomPane.prototype = {
	
	element: null,
	options: {},
	
	initialize: function(element) {
		this.options = Object.extend({
			height: null,
			transition: Effect.Transitions.ultrasmooth,
			duration: 1.0,
			delay: 0.0,
			beforeShow: null,
			afterShow: null,
			beforeHide: null,
			afterHide: null,
			autoFix: false,
			offset: 0,
			adjust: 0
		}, arguments[1] || {});			
		this.element = $(element);
		this.recalculate();
		if(this.options.autoFix) {
			this.element.parentNode.style.overflow = 'hidden';
			dim_p = Element.getDimensions(this.element.parentNode);
			Element.setDimensions(this.element.parentNode, dim_p.width, dim_p.height);
		}		
	},
	
	set_shown: function() {
		Element.setStyle(this.element, { bottom: this.options.offset });		
	},
	
	set_hidden: function() {
		Element.setStyle(this.element, { bottom: (this.options.offset - this.elementHeight) + 'px' });
	},
	
	show: function() {
		new Effect.MoveFromBottom(this.element, { mode: 'absolute', y: this.options.offset,
			delay: this.options.delay, duration: this.options.duration, transition: this.options.transition,
			beforeStart: this.options.beforeShow, afterFinish: this.options.afterShow });
	},
	
	hide: function() {
		new Effect.MoveFromBottom(this.element, { mode: 'absolute', y: (this.options.offset - this.elementHeight),
			delay: this.options.delay, duration: this.options.duration, transition: this.options.transition,
			beforeStart: this.options.beforeHide, afterFinish: this.options.afterHide });
	},
	
	toggle: function() {
		if(this.is_hidden()) { this.show(); } else { this.hide(); }
	},
	
	is_shown: function() {
		return (parseFloat(Element.getStyle(this.element, 'bottom')  || this.options.offset)) == this.options.offset;
	},
	
	is_hidden: function() {
		return !this.is_shown();
	},
	
	recalculate: function() {
		dim_e = Element.getDimensions(this.element);
		this.elementHeight = (this.options.height || dim_e.height) + this.options.adjust;
	}
	
}



Effect.SlideBackgroundImage = Class.create();
Object.extend(Object.extend(Effect.SlideBackgroundImage.prototype, Effect.Base.prototype), {
	
	/***
	
	- description: slide the background image in- or out of view (css)
	
	***/
	
	initialize: function() {
		this.element = $(arguments[0] || document.rootElement);
		this.options = {};
		
		var options = Object.extend({
			from: 0.0,
			to:   1.0,
			min: 0,
			max: 'auto',
			direction: 'w',
			fade: 'in',
			origin: 0
		}, arguments[1] || {});
		
		if(options.max == 'auto') { options.max = this.autoSetMax(options); }
		this.start(options);	
	},
	
	autoSetMax: function(options) {
		if(options.direction == 'w' || options.direction == 'right' || options.direction == 'e' || options.direction == 'left') { // horizontal	
			return Element.getStyleWidth(this.element);		
		} else if(options.direction == 'n' || options.direction == 'down' || options.direction == 's' || options.direction == 'up') { // vertical				
			return Element.getStyleHeight(this.element);	
		}
		return 100;
	},
	
	update: function(position) {
		if(this.options.fade == 'in') {
			this.setBgPositionIn(position);
		} else {
			this.setBgPositionOut(position);
		}
	}, 
		
	setBgPositionIn: function(position) {
		var direction = this.options.direction;
		if(direction == 'w' || direction == 'right') { // move west
			this.element.style.backgroundPosition = (-(this.options.max + this.options.min) + Math.round(position*this.options.max)) + 'px ' + this.options.origin;
		} else if(direction == 'e' || direction == 'left') { // move east		
			this.element.style.backgroundPosition = ((this.options.max + this.options.min) - Math.round(position*this.options.max)) + 'px ' + this.options.origin;			
		} else if(direction == 'n' || direction == 'down') { // move north
			this.element.style.backgroundPosition = this.options.origin + ' ' + (-(this.options.max + this.options.min) + Math.round(position*this.options.max)) + 'px';				
		} else if(direction == 's' || direction == 'up') { // move south				
			this.element.style.backgroundPosition = this.options.origin + ' ' + ((this.options.max + this.options.min) - Math.round(position*this.options.max)) + 'px';	
		} else {
			this.element.style.backgroundPosition = this.options.origin + 'px ' + this.options.origin + 'px';
		}
	},
	
	setBgPositionOut: function(position) {
		var direction = this.options.direction;
		if(direction == 'w' || direction == 'left') { // move west
			this.element.style.backgroundPosition = (-Math.round(position*this.options.max) + this.options.min) + 'px ' + this.options.origin;	
		} else if(direction == 'e' || direction == 'right') { // move east	
			this.element.style.backgroundPosition = (this.options.min + Math.round(position*this.options.max)) + 'px ' + this.options.origin;				
		} else if(direction == 'n' || direction == 'up') { // move north
			this.element.style.backgroundPosition = this.options.origin + ' ' + (- Math.round(position*this.options.max) + this.options.min) + 'px';					
		} else if(direction == 's' || direction == 'down') { // move south			
			this.element.style.backgroundPosition = this.options.origin + ' ' + (this.options.min + Math.round(position*this.options.max)) + 'px';
		} else {
			this.element.style.backgroundPosition = this.options.origin + 'px ' + this.options.origin + 'px';
		}
	}

});

Effect.MoveBackgroundImage = Class.create();
Object.extend(Object.extend(Effect.MoveBackgroundImage.prototype, Effect.Base.prototype), {
	
	/***
	
	- description: slide the background using relative or absolute positioning
	
	***/
	
	origin: null, deltaX: 0, deltaY: 0,
	
	initialize: function(elem, newLeft, newTop) {
		this.element = $(elem);
		
		var options = Object.extend({
			from: 0.0,
			to:   1.0,
			origin: false,
			offset: [0, 0],
			absolute: true
		}, arguments[3] || {});
		
		if(Var.is_array(options.origin)) {
			// origin is set in options
			this.origin = options.origin;
		} else {
			// be sure to have inline or javascript definition of background-position set
			var currentPosition = Element.Style.getBackgroundPosition(this.element, true);	
			if(Var.is_array(currentPosition)) {
				this.origin = [ currentPosition[0], currentPosition[1] ];
			} else {
				this.origin = [ 0, 0 ];
			}
		}
		if(Var.is_array(this.origin)) { 
			if(options.absolute) {
				this.deltaX = newLeft - this.origin[0] + options.offset[0];
				this.deltaY = newTop - this.origin[1] + options.offset[1];
			} else {
				this.deltaX = newLeft;
				this.deltaY = newTop;
			}
		} 
		this.start(options);
	},
	
	update: function(position) {
		var pLeft = (this.deltaX * position) + this.origin[0];
		var pTop = (this.deltaY * position) + this.origin[1];
		this.element.style.backgroundPosition = pLeft + 'px ' + pTop + 'px';
	}

});

Effect.BackgroundScroll = Class.create();
Object.extend(Object.extend(Effect.BackgroundScroll.prototype, Effect.Base.prototype), {
	initialize: function(element) {
		this.element = $(element);
		this.options['step'] = 20;
		if(!this.element.currentBackgroundPosition)
		this.element.currentBackgroundPosition = [0, 0];
		this.offsets = arguments[1];
		this.start(arguments[2] || {});
	},
	setup: function() {
		this.current = this.element.currentBackgroundPosition;
		this.delta = [
		this.offsets[0] - this.current[0] - Math.round(Math.random()*this.options['step']),
		this.offsets[1] - this.current[1] - Math.round(Math.random()*this.options['step'])];
	},
	update: function(position) {
		this.element.currentBackgroundPosition = [
		Math.round(this.current[0] + (this.delta[0]*position)),
		Math.round(this.current[1] + (this.delta[1]*position)) ];
		this.element.style.backgroundPosition = 
		this.element.currentBackgroundPosition[0] + 'px ' +
		this.element.currentBackgroundPosition[1] + 'px';
	}
});


