/**
 * Location:	/backbone/js/effects.js
 * Copyright:	Neist & Felskov, 2009+
 *
 * Author:		Neist & Felskov
 * Mail:		kontakt@nfdesign.dk
 * Web:			www.nfdesign.dk
 *
 ***********
 *
 * Indeholder funktioner, der bruges til at lave glidende effekter/animationer.
 */

/**
 * handleEffects
 *
 **********
 *
 * Sørger for at køre effekterne.
 */
function handleEffects(){
	// Udregn timestamp
	var time=new Date().getTime();

	// Gennemgå alle effekter
	var i=effects.length; var j=i;
	if(i>0)do{effects[j-i] && effects[j-i].loop(time);}while(--i);
}
effects=[];
setInterval(handleEffects,15);

/**
 * Effect
 *
 **********
 *
 * Håndterer animationer og effekter, der skal køres glidende.
 *
 **********
 *
 * Parametre:
 * handler (function)					Funktion der skal håndtere effekten.
 * settings (array)						Indstillingerne for effekten:
 *										- duration (int): sekunder effekten skal vare
 *										- ease (boolean): skal der eases ind?
 */
function Effect(handler,settings){
	// Indlæs indstillinger
	this.handler=handler;							// Gem handler-funktionen
	this.duration=(settings.duration||1)*1000;		// Hvor længe skal den vare i millisekunder
	this.ease=settings.ease||false;					// Skal der eases?

	// Klargør variabler
	this.pos=0;										// Vi starter ved position 0
	this.last=new Date().getTime();;

	// Tilføj til effect-handleren
	this.effectID=effects.length;
	effects[this.effectID]=this;
}

/**
 * loop
 *
 **********
 *
 * Loopes mens effekten er aktiv, og udregner status.
 *
 **********
 *
 * Parametre:
 * time (int)							Indeholder det nuværende timestamp.
 */
Effect.prototype.loop=function(time){
	// Udregn status for hvor langt animationen er nået
	this.pos+=(time-this.last)/this.duration;			// Udregn hvor langt vi er nået siden sidste frame
	this.last=time;										// Gem det aktuelle timestamp
	var pos=Math.min(1,this.pos);						// Vi kan ikke nå længere end 100%
	if(this.ease==1) pos=Math.sin(Math.sin(pos*Math.PI/2)*Math.PI/2);		// Håndter easing

	// Kør handler-funktionen
	if(pos<1){
		this.handler(pos);

	// Afslut animationen
	}else{
		// Kør handleren med 100%
		this.handler(1);

		// Afbryd intervallet
		delete effects[this.effectID];

		// Ryd hukommelsen
		this.handler=null; this.duration=null; this.ease=null; this.totalFrames=null; this.currentFrame=null; this.start=null; this.effectID=null;
	}
}

/**
 * DragDrop
 *
 **********
 *
 * Håndterer drag'n'drop af elementer.
 *
 **********
 *
 * Parametre:
 * e (eventinfo)						Informationer om brugerens inputs.
 * handlers (array)						Angiv en liste over handler-funktioner.
 *										- drag: Køres ved mousemove.
 *										- drop: Køres ved mouseup.
 */
function DragDrop(e,handlers){
	// Indlæs brugerens inputs
	var e=e||window.event;

	// Klargør variabler
	this.handlers=handlers;

	// Håndter drag'n'drop
	if(document.attachEvent){
		document.attachEvent('onmousemove',DragDrop.prototype.drag);
		document.attachEvent('onmouseup',DragDrop.prototype.drop);
	}else{
		document.addEventListener('mousemove',DragDrop.prototype.drag,false);
		document.addEventListener('mouseup',DragDrop.prototype.drop,false);
	}

	// Registrer hvor brugeren klikkede (FF)
	if(e.pageX || e.pageY){
		this.x=e.pageX;
		this.y=e.pageY;

	// ... (IE)
	}else{
		this.x=e.clientX+document.body.scrollLeft-document.body.clientLeft;
		this.y=e.clientY+document.body.scrollTop-document.body.clientTop;
	}

	// Gem informationerne i browserens hukommelse
	dragObject=this;

	// Fortæl browseren, at den ikke skal håndtere drag'n'drop
	stopEvent(e);
}

/**
 * drag
 *
 **********
 *
 * Håndterer mousemove-eventet, når der drag'n'droppes.
 *
 **********
 *
 * Parametre:
 * e (eventinfo)						Indeholder informationer om brugerens input.
 */
DragDrop.prototype.drag=function(e){
	// Registrer musens bevægelse
	if(e.pageX || e.pageY){
		var x=e.pageX-dragObject.x;
		var y=e.pageY-dragObject.y;

	// ... (IE)
	}else{
		var x=e.clientX+document.body.scrollLeft-document.body.clientLeft-dragObject.x;
		var y=e.clientY+document.body.scrollTop-document.body.clientTop-dragObject.y;
	}

	// Send informationerne om musens bevægelse tilbage til handleren
	dragObject.handlers.drag(dragObject.handlers.element,x,y);

	// Fortæl browseren, at den ikke skal håndtere drag'n'drop
	stopEvent(e);
}

/**
 * drop
 *
 **********
 *
 * Håndterer mouseup-eventet, når der drag'n'droppes.
 *
 **********
 *
 * Parametre:
 * e (eventinfo)						Indeholder informationer om brugerens input.
 */
DragDrop.prototype.drop=function(e){
	// Registrer musens bevægelse
	if(e.pageX || e.pageY){
		var x=e.pageX-dragObject.x;
		var y=e.pageY-dragObject.y;

	// ... (IE)
	}else{
		var x=e.clientX+document.body.scrollLeft-document.body.clientLeft-dragObject.x;
		var y=e.clientY+document.body.scrollTop-document.body.clientTop-dragObject.y;
	}

	// Send informationerne om musens bevægelse tilbage til handleren
	dragObject.handlers.drop(dragObject.handlers.element,x,y);

	// Afbryd drag'n'drop-håndtering
	if(document.detachEvent){
		document.detachEvent('onmousemove',DragDrop.prototype.drag);
		document.detachEvent('onmouseup',DragDrop.prototype.drop);
	}else{
		document.removeEventListener('mousemove',DragDrop.prototype.drag,false);
		document.removeEventListener('mouseup',DragDrop.prototype.drop,false);
	}

	// Ryd browserens hukommelse
	dragObject=null;

	// Fortæl browseren, at den ikke skal håndtere drag'n'drop
	stopEvent(e);
}

/**
 * stopEvent
 *
 **********
 *
 * Afbryder eksekveringen af et event på kryds af browsere.
 *
 **********
 *
 * Parametre:
 * e (eventinfo)						Informationer om brugerens input.
 */
function stopEvent(e){
	// Stop eventet på alle tænkelige måder
	if(e.preventDefault) e.preventDefault();
	if(e.stopPropagation) e.stopPropagation();
	if(e.stop) e.stop();
	if(document.all&&e.keyCode) try{e.keyCode=0;}catch(e){}
	e.cancelBubble=true;
	e.returnValue=false;
}
