/*
Script: Fx.Tween.js
	Formerly Fx.Style, effect to transition any CSS property for an element.

License:
	MIT-style license.
*/

Fx.Shake = new Class({

	Extends: Fx.Tween,

	options: {
		times: 5
	},

	initialize: function(){
		this.parent.apply(this, arguments);
		if (this.options.property) {
			this.property = this.options.property;
			delete this.options.property;
		}
		this._start = this.start;
		this.start = this.shake;
		this.duration = this.options.duration;
		this.shakeChain = new Chain();
	},

	complete: function(){
		if (!this.shakeChain.$chain.length && this.stopTimer()) this.onComplete();
		else if (this.shakeChain.$chain.length) this.shakeChain.callChain();
		return this;
	},

	shake: function(property, distance, times){
		if (!this.check(arguments.callee, property, distance)) return this;
		var args = Array.link(arguments, {property: String.type, distance: $defined, times: $defined});
		property = this.property || args.property;
		times = args.times || this.options.times;
		this.stepDur = this.duration / (times + 1);
		this._getTransition = this.getTransition;
		this.origin = this.element.getStyle(property).toInt()||0;
		this.shakeChain.chain(
			function(){
				this.shakeChain.chain(
					function() {
							this.stopTimer();
							this.getTransition = this._getTransition;
							this.options.duration = this.stepDur / 2;
							//stage three, return to origin
							this._start(property, this.origin);
					}.bind(this)
				);
				this.getTransition = function(){
					return function(p){
						return (1 + Math.sin( times*p*Math.PI - Math.PI/2 )) / 2;
					}.bind(this);
				}.bind(this);
				this.stopTimer();
				this.options.duration = this.stepDur * times;
				//stage 2: offset to the other side using the shake transition
				this._start(property, this.origin - args.distance);
			}.bind(this)
		);
		this.options.duration = this.stepDur / 2;
		//stage 1: offset to one side
		return this._start(property, this.origin + args.distance);
	},

	onCancel: function(){
		this.parent();
		this.shakeChain.clearChain();
		return this;
	}

});

Element.Properties.shake = {

	set: function(options){
		var shake = this.retrieve('shake');
		if (shake) shake.cancel();
		return this.eliminate('shake').store('shake:options', $extend({link: 'cancel'}, options));
	},

	get: function(options){
		if (options || !this.retrieve('shake')){
			if (options || !this.retrieve('shake:options')) this.set('shake', options);
			this.store('shake', new Fx.Shake(this, this.retrieve('shake:options')));
		}
		return this.retrieve('shake');
	}

};

Element.implement({

	shake: function(property, distance, times, options){
		var args = Array.link(arguments, {property: String.type, distance: Number.type, times: Number.type, options: Object.type});
		if (args.options) this.set('shake', args.options);
		this.get('shake').start(args.property, args.distance, args.times);
		return this;
	}

})

/* shake baby! */
window.addEvent('domready',function() {
  var shaker = $('shaker');
  shaker.setStyles({
    opacity: 0,
    display: 'block'
  });
  /* event */
  window.addEvent('load',function() {
    /* fade in */
    var x = function() { shaker.fade('in');};
    x.delay(1000);
    /* shake */
    var y = function() { shaker.shake('margin',5,3); };
    y.periodical(3000);
  });
});

