// scroller.js

/*
	scroller.js - performs scrolling effect on projects index page
	
	Requires mootools 1.2 and Fx.Scroll addon
*/


var s = {
	
	scroller : '', // holds Fx.Scroll instance
	element : 'artist-list-inner', // container element id
	upbtn : 'artist-list-controls-up', // up button element id
	dwnbtn : 'artist-list-controls-down', // down button element id
	scrollSpeed : 25, // speed of scrolling when using keys
	intervalId : '', // holds scroll periodical index
	increase : 1, // used by scrolling to 
	pos : 0, // holds start position used to calculate velocity
	time : 0, // holds start time for calulating velocity
	a : 1000, // 'magic number' - represents implied friction of object
	dir : '', // holds scroll direction
	debug : false, // if true, will output debugging info
	
/*
	init():void
		initialises code - creates Fx.Scroll object and adds events
*/
		
	init: function(){
		
		s.scroller = new Fx.Scroll(s.element, {transition:'quint:out'} );
		$(s.upbtn).addEvent('mouseover', s.startScrollUp);
		$(s.upbtn).addEvent('mouseout', s.stopScroll);
		$(s.dwnbtn).addEvent('mouseover', s.startScrollDown);
		$(s.dwnbtn).addEvent('mouseout', s.stopScroll);
		s.scroller.set(0, 10);
		$(s.element).addEvent('mousedown', s.grab);
		$(s.element).addEvent('mouseup', s.letGo);
		$(document).addEvent('keydown', s.keyScroll);
		$(document).addEvent('keyup', s.stopScroll);
	},
/*
	trace(m:String):void
		used internally to output debugging info
*/
	
	trace: function(m){
		if(s.debug){
			console.log(m);
		}
	},

/*
	keyScroll(ev:Event):void
		Received key event and scrolls accordingly
		Params:
			ev - Event Object
		Called By : Event(keydown)
*/
	keyScroll: function(ev){
		var e = new Event(ev);
		if(e.alt && e.key == 'up'){
			s.scroller.set(0, $(s.element).getScroll().y - 10);
		}else if(e.alt && e.key == 'down'){
			s.scroller.set(0, $(s.element).getScroll().y + 10);
		}
	},

/*
	calculateVelocity(d:Number, t:Number):Number
		calculates velocity, distance travelled divided by time taken
		Params:
			d - the distance travelled
			t - the time taken
		Called By: dragScroll
*/		
	calculateVelocity: function(d, t){
		return (d / t) * s.a;
	},
	
/*
	calculateTime():Number
		Calculates the amount of time to continue scrolling after user lets go
		Called By: letGo
*/
	calculateTime: function(){
		return (s.velocity / s.a) * 100;
	},
	
/*
	calculateDistance():Number
		calculates the amount of scrolling after the user lets go
		Called By: letGo
*/
	calculateDistance: function(){
		return (s.velocity * s.velocity) / (s.a * 4) ;
	},
	
/*
	grab(ev:Event):void
		fired by mousedown event, when user 'grabs' the scrollable text
		Called By: Event(s.element.mousedown)
		Params : ev - Event Object
*/
	grab: function(ev){
		s.scroller.cancel();
		$(s.element).addEvent('mouseleave', s.letGo);
		s.pos = 0;
		s.time = 0;
		var e = new Event(ev);
		e.stop();
		var d = new Date();
		s.pos = e.page.y;
		s.time = d.getTime();
		s.trace('element grabbed.  Pos is ' + s.pos + ', time is ' + s.time);
		$(s.element).addClass('active');
		$(s.element).addEvent('mousemove', s.dragScroll);
	},
	
/*
	removeDrag():void
		removes the drag effect
		Called by: letGo
*/
	removeDrag: function(){
		$(s.element).removeEvent('mousemove', s.dragScroll);
	},
	
	letGo: function(ev){
		var e = new Event(ev);
		$(s.element).removeClass('active');
		s.removeDrag();
		//s.scroller.options.duration = (s.calculateTime() ).round();
		var dist = s.calculateDistance().round();
		s.trace('element released.  dist is ' + dist + ', direction is ' + s.dir);
		$(s.element).removeEvent('mouseleave', s.letGo);
		if(s.dir == 'down'){
			s.scroller.start(0, $(s.element).getScroll().y + dist );
		}else if(s.dir == 'up'){
			s.scroller.start(0, $(s.element).getScroll().y - dist );
		}
	},
	
	dragScroll: function(ev){
		var e = new Event(ev);
		e.stop();
		var d = new Date();
		var pos = e.page.y;
		var diff = s.pos - pos;
		var posDiff;
		if( diff < 0 ){
			s.dir = 'up';
			posDiff = diff * diff;
		}else{
			s.dir = 'down';
			posDiff = diff;
		}
		var timeDiff = d.getTime() - s.time;
		s.pos = pos;
		s.time = d.getTime();
		s.velocity = s.calculateVelocity(posDiff, timeDiff);
		var y = $(s.element).getScroll().y  + diff;
		if( y < 0) y = 0;
		if( y >  $(s.element).getScrollSize().y ) y = $(s.element).getScrollSize().y;
		s.scroller.set(0, y);
	},
	
	startScrollUp: function(){
		var i= 1000 / s.scrollSpeed;
		var i = i.round();
		s.intervalId = s.scrollUp.periodical(i );
	},
	
	startScrollDown: function(){
		var i = 1000 / s.scrollSpeed;
		var i = i.round();
		s.intervalId = s.scrollDown.periodical(i);
	},
	
	stopScroll: function(){
		$clear(s.intervalId);
		s.increase = 1;
	},
	
	scrollUp: function(){
		s.increase++;
		var y = $(s.element).getScroll().y - s.increase;
		if( y < 10 ) s.stopScroll();
		s.scroller.set(0, y);
	},
	
	scrollDown: function(){
		s.increase++;
		var y = $(s.element).getScroll().y + s.increase;
		if(y > $(s.element).getScrollSize().y - 10) s.stopScroll();
		s.scroller.set(0, y);
	}
}

if(s.debug){
try{
	console.log();
}catch(e){
	var console = {};
	console.win = window.open('', 'Debugger', 'width=250,height=200');
	console.win.document.write('<h2>Debugging Console</h2>');
	console.log = function(m){
		console.win.document.write(m + '<br />');
	}
}
}

window.addEvent('domready', s.init);
