Effect.PAIRS = Object.extend(
	Effect.PAIRS, { 
		'slidedown':  ['SlideDownIn',  'SlideDownOut'],
		'slideup':    ['SlideUpIn',    'SlideUpOut'],
		'slideleft':  ['SlideLeftIn',  'SlideLeftOut'],
		'slideright': ['SlideRightIn', 'SlideRightOut'],
		'curtain':    ['CurtainClose', 'CurtainOpen']
	}
);


Object.extend(
	Effect, {
		_elementIsNotAListError: {
			name: 'ElementIsNotAListError',
			message: 'The specified DOM element is not a list exist, but is required to be for this effect to operate'
		}
  }
);



Effect.SlideLeftIn = function(element) {
	element = $(element).cleanWhitespace();
	if ( ! element.effectOn ) {
		element.effectOn = true;
		var elementDimensions = element.getDimensions();
		return new Effect.Parallel ( [
			new Effect.Move(element, 
				Object.extend({ 
					x: -(elementDimensions.width), 
					sync: true, 
					mode: 'relative', 
					beforeStartInternal: function(effect) {
						if(window.opera) effect.element.setStyle({left: ''});
						effect.element.setStyle({left: elementDimensions.width + 'px' });
						effect.element.show();
					}
				}, arguments[1] || {})
			),
			new Effect.Scale(element, 100,
				Object.extend({ scaleContent: false, 
					/* why does the use of sync: true make this flicker? */
					scaleY: false,
					scaleFrom: window.opera ? 0 : 1
				}, arguments[1] || {})
			)
			], Object.extend({
				beforeSetup: function(effect){
					effect.effects[0].element.parentNode.makeClipping();
					effect.effects[0].element.makeClipping();
				},
				afterFinishInternal: function(effect){
					effect.effects[0].element.parentNode.undoClipping();
					effect.effects[0].element.undoClipping();
				},
				afterFinish: function(effect){
//					delete(effect.effects[0].element.effectOn);
					effect.effects[0].element.effectOn = false;
				}
			}, arguments[1] || {})
		);
	}
}


Effect.SlideRightOut = function(element) {
	element = $(element).cleanWhitespace();
	var elementDimensions = element.getDimensions();
	return new Effect.Parallel ( [
		new Effect.Move(element, { x: element.getWidth() - 10 , sync: true, mode: 'relative' }),
		new Effect.Scale(element, window.opera ? 0 : 1, {	
			sync: true, 
			scaleContent: false, 
			scaleY: false,
			scaleFrom: 100,
			restoreAfterFinish: true
		})
		], Object.extend({ 
			beforeSetup: function(effect){
				effect.effects[0].element.makeClipping();
			},
			afterFinishInternal: function(effect){
				effect.effects[0].element.undoClipping().hide();
			}
		}, arguments[1] || {})
	);
}



Effect.SlideLeftOut = function(element) {
	element = $(element).cleanWhitespace();
	return new Effect.Scale(element, window.opera ? 0 : 1,
		Object.extend({ 
			scaleContent: false, 
			scaleY: false, 
			scaleMode: 'box',
			scaleFrom: 100,
			restoreAfterFinish: true,
			beforeStartInternal: function(effect) {
				effect.element.makePositioned();
				effect.element.down().makePositioned();
				if(window.opera) effect.element.setStyle({left: ''});
				effect.element.makeClipping().show();
			},  
			afterUpdateInternal: function(effect) {
				effect.element.down().setStyle(
					{right: (effect.dims[1] - effect.element.clientWidth) + 'px' }
				);
			},
			afterFinishInternal: function(effect) {
				effect.element.hide().undoClipping().undoPositioned();
				effect.element.down().undoPositioned();
			}
		}, arguments[1] || {})
	);
}


Effect.SlideRightIn = function(element) {
	element = $(element).cleanWhitespace();
	var elementDimensions = element.getDimensions();
	return new Effect.Scale(element, 100, 
		Object.extend({ 
			scaleContent: false, 
			scaleY: false, 
			scaleFrom: window.opera ? 0 : 1,
			scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
			restoreAfterFinish: true,
			afterSetup: function(effect) {
				effect.element.makePositioned();
				//effect.element.down().makePositioned();
				if(window.opera) effect.element.setStyle({left: ''});
				effect.element.makeClipping().setStyle({width: '0px'}).show(); 
			},
			afterUpdateInternal: function(effect) {
				//effect.element.down().setStyle({right: (effect.dims[1] - effect.element.clientWidth) + 'px' }); 
			},
			afterFinishInternal: function(effect) {
				effect.element.undoClipping().undoPositioned();
				//effect.element.down().undoPositioned();
			}
		}, arguments[1] || {})
	);
}



Effect.SlideUpIn = function(element) {
	element = $(element).cleanWhitespace();
	var elementDimensions = element.getDimensions();
	return new Effect.Parallel ( [
		new Effect.Move(element, { y: -(element.getHeight()), sync: true, mode: 'relative' }),
		new Effect.Scale(element, 100, 
			Object.extend({
				sync: true,
				scaleContent: false,
				scaleX: false,
				scaleFrom: 0,
				scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
				beforeSetup: function(effect) {
					effect.element.hide();
				},
				afterSetup: function(effect) {
					effect.element.makeClipping().setStyle({height: '0px'}).show();
				},
				afterFinishInternal: function(effect) {
					effect.element.undoClipping();
				}
			}, arguments[1] || {})
		)
	], Object.extend({
		afterSetup: function(effect) {
			effect.effects[0].element.setStyle({top: elementDimensions.height + 'px' });
		}
	}, arguments[1] || {}));
}


Effect.SlideDownOut = function(element) {
	element = $(element).cleanWhitespace();
	var elementDimensions = element.getDimensions();
	return new Effect.Parallel ( [
		new Effect.Move(element, { y: element.getHeight(), sync: true, mode: 'relative' }),
		new Effect.Scale(element, 0,
			Object.extend({ 
				sync: true,
				scaleContent: false,
				scaleX: false,
				restoreAfterFinish: true,
				beforeSetup: function(effect){
					effect.element.makeClipping();
				},
				afterFinishInternal: function(effect) {
					effect.element.hide().undoClipping();
				}
			}, arguments[1] || {})
		)
	], Object.extend({
	}, arguments[1] || {}));
}



Effect.SlideDownIn = function(element) {
	element = $(element).cleanWhitespace();
	var oldInnerBottom = element.down().getStyle('bottom');
	var elementDimensions = element.getDimensions();
	return new Effect.Scale(element, 100, 
		Object.extend({ 
			scaleContent: false, 
			scaleX: false, 
			scaleFrom: window.opera ? 0 : 1,
			scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
			restoreAfterFinish: true,
			afterSetup: function(effect) {
				effect.element.makePositioned();
				effect.element.down().makePositioned();
				if(window.opera) effect.element.setStyle({top: ''});
				effect.element.makeClipping().setStyle({height: '0px'}).show(); 
			},
			afterUpdateInternal: function(effect) {
				effect.element.down().setStyle({bottom:
				(effect.dims[0] - effect.element.clientHeight) + 'px' }); 
			},
			afterFinishInternal: function(effect) {
				effect.element.undoClipping().undoPositioned();
				effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); 
			}
		}, arguments[1] || {})
	);
}

Effect.SlideUpOut = function(element) {
	element = $(element).cleanWhitespace();
	var oldInnerBottom = element.down().getStyle('bottom');
	return new Effect.Scale(element, window.opera ? 0 : 1,
		Object.extend({ 
			scaleContent: false, 
			scaleX: false, 
			scaleMode: 'box',
			scaleFrom: 100,
			restoreAfterFinish: true,
			beforeStartInternal: function(effect) {
				effect.element.makePositioned();
				effect.element.down().makePositioned();
				if(window.opera) effect.element.setStyle({top: ''});
				effect.element.makeClipping().show();
			},  
			afterUpdateInternal: function(effect) {
				effect.element.down().setStyle({bottom:
				(effect.dims[0] - effect.element.clientHeight) + 'px' });
			},
			afterFinishInternal: function(effect) {
				effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
				effect.element.down().undoPositioned();
			}
		}, arguments[1] || {})
	);
}