/**
 * @projectDescription	MooTools Scrollbar
 * credit to http://solutoire.com/2008/03/10/mootools-css-styled-scrollbar/
 * 
 * @author	Ryan Sullivan ryan@thresholdinteractive.com
 * @version 0.4
 * requires MooTools 1.11+
 * 
 * History:
 * 0.5 (20080717):		scrollbar slider can be fixed to match scrolling content
 * 0.4 (20080715):		added content jumping (smooth scrolling directly to area within content)
 * 0.3 (20080711):		scrollbar only appears if necessary and automatically readjusts if content scroll size changes
 * 0.2 (20080626):		added functionality to reconstruct an existing scrollbar
 * 0.1 (20080601):		initial build
 */
if(typeof(threshold)=="undefined"){threshold={};}
threshold.scrollbar = function() {
	var win=window,doc=document;
	var controls = new Hash({});
	var scrollJump,scrollFix;
	var wrapContent=function(content){
		var wrapper = new Element('div',{'class':content.getProperty('class'),'styles':{'overflow':'hidden'}});
		wrapper.addClass('scrollbar-wrapper');
		content.setProperty('class','');
		content.addClass('scrollbar-content');
		content.setStyle('overflow','hidden');
		wrapper.injectBefore(content);
		wrapper.adopt(content);
	};
	var createScrollbar=function(content,horizontal,noWheel){
		var size = (MooTools.version==1.11) ? content.getSize().size.y : content.getSize().y;
		var scrollSize = (MooTools.version==1.11) ? content.getSize().scrollSize.y : content.getScrollSize().y;
		if(size>=scrollSize){remove(content);return;}
		if(controls.get(content).scrollSize==scrollSize&&content.getNext('.scrollbar')){return;}
		controls.get(content).scrollSize = scrollSize;
		remove(content);
		var scrollbar = new Element('div',{'class':'scrollbar'});
		var track = new Element('div',{'class':'scrollbar-track'});
		var thumb = new Element('div',{'class':'scrollbar-thumb'}).injectInside(track);
		track.injectInside(scrollbar);
		// add arrows
		var arrow0 = new Element('div',{
			'class':'scrollbar-arrow-first-'+(horizontal?'horizontal':'vertical'),
			'styles':{'cursor':'pointer'}
		}).setHTML(horizontal?'&#9668;':'&#9650;').injectBefore(track);
		var arrow1 = new Element('div',{
			'class':'scrollbar-arrow-last-'+(horizontal?'horizontal':'vertical'),
			'styles':{'cursor':'pointer'}
		}).setHTML(horizontal?'&#9658;':'&#9660;').injectAfter(track);
		if(horizontal){
			track.setStyle('float','left');
			arrow0.setStyle('float','left');
			arrow1.setStyle('float','left');
		} else {
			content.setStyle('float','left');
			scrollbar.setStyle('float','right');
		}
		scrollbar.injectAfter(content);
		addBehavior(content,track,thumb,horizontal,[arrow0,arrow1],noWheel);
	};
	var addBehavior=function(content,track,thumb,horizontal,arrows,noWheel){
		var steps = (MooTools.version==1.11) ? content.getSize().scrollSize.y - content.getSize().size.y : (horizontal?(content.getScrollSize().x - content.getSize().x):(content.getScrollSize().y - content.getSize().y));
		var slider = new Slider(track, thumb, {
			steps: steps,
			mode: (horizontal?'horizontal':'vertical'),
			onChange: function(step){
				if(scrollFix){scrollFix=false;return;}
				// Scrolls the content element in x or y direction.
				var x = (horizontal?step:0);
				var y = (horizontal?0:step);
				if(scrollJump){
					var scroll = new Fx.Scroll(content).scrollTo(x,y);
					scrollJump = false;
				} else {
					content.scrollTo(x,y);
				}
			}
		});
		controls.get(content).slider = slider;
		var scrollStep=function(e){
			e = new Event(e).stop();
			scrollJump = false;
			var direction = e.wheel||e.target.getProperty('class').indexOf('scrollbar-arrow-first')||1;
			var step = slider.step - direction * 30;
			slider.set(step);

			// prevent arrow from being selected
			if(win.getSelection) {
				var sel = win.getSelection();
				if(sel&&sel.removeAllRanges){sel.removeAllRanges();}
			} else if(doc.selection&&doc.selection.empty) {
				doc.selection.empty();
			}
		};
		var scrollStepInterval;
		arrows.each(function(el){
			el.removeEvents();
			el.addEvents({
				'mousedown':function(e){scrollStepInterval=function(){scrollStep(e);}.periodical(50);},
				'mouseup':function(e){$clear(scrollStepInterval);},
				'click':scrollStep
			});
		});
		if(!noWheel){
			// Scroll the content element when the mousewheel is used within the 
			// content or the scrollbar element.
			$$(content, track).removeEvents('mousewheel');
			$$(content, track).addEvent('mousewheel',scrollStep);
		}
		// Stops the handle dragging process when the mouse leaves the document body.
		//$(document.body).removeEvents('mouseleave');
		//$(document.body).addEvent('mouseleave',function(){slider.drag.stop();});
	};
	var remove=function(content){
		if(content.hasClass('scrollbar-content')){
			if (content.getNext('.scrollbar')){
				content.getNext('.scrollbar').remove();
			}
		}
	};

	// public members
	return{
		addTo:function(content,horizontal,noWheel){
			wrapContent(content);
			controls.set(content,{
				scrollSize:(MooTools.version==1.11) ? content.getSize().scrollSize.y : content.getScrollSize().y,
				interval:function(){createScrollbar(content, horizontal, noWheel);}.periodical(50),
				jump:function(step){
					if(!this.slider){return;}
					scrollJump=true;
					this.slider.set(step);
				},
				fix:function(){
					if(!this.slider){return;}
					scrollFix=true;
					this.slider.set((MooTools.version==1.11) ? content.getSize().scroll.y : content.getScroll().y);
				}
			});
		},
		remove:remove,
		controls:controls
	};
}();

