(function($) {
	$.tiny = $.tiny||{};
	$.tiny.scrollbar = {
		options:{
			axis:'y',
			wheel:40,
			scroll:true,
			size:'auto',
			sizethumb:'auto'
		}
	};
	$.fn.tinyscrollbar = function(options) {
		var options = $.extend({},$.tiny.scrollbar.options,options);
		this.each(function() {
			$(this).data('tsb',new Scrollbar($(this),options));
		});
		return this;
	};
	$.fn.tinyscrollbar_update = function(sScroll) {
		return $(this).data('tsb').update(sScroll);
	};
	function Scrollbar(root,options) {
		var oSelf = this;
		var oWrapper = root;
		var oViewport = {
			obj:$('.viewport',root)
		};
		var oContent = {
			obj:$('.overview',root)
		};
		var oScrollbar = {
			obj:$('.scrollbar',root)
		};
		var oTrack = {
			obj:$('.track',oScrollbar.obj)
		};
		var oThumb = {
			obj:$('.thumb',oScrollbar.obj)
		};
		var sAxis = options.axis == 'x',sDirection=sAxis ? 'left' : 'top',sSize=sAxis ? 'Width' : 'Height';
		var iScroll,iPosition = {start:0,now:0},iMouse={};
		function initialize() {
			oSelf.update();setEvents();
		return oSelf;
		}
		this.update = function(sScroll){
			oViewport[options.axis] = oViewport.obj[0]['offset' + sSize];
			oContent[options.axis] = oContent.obj[0]['scroll' + sSize];
			oContent.ratio = oViewport[options.axis]/oContent[options.axis];
			oScrollbar.obj.toggleClass('disable',oContent.ratio >= 1);
			oTrack[options.axis] = options.size == 'auto' ? oViewport[options.axis] : options.size;
			oThumb[options.axis] = Math.min(oTrack[options.axis],Math.max(0,(options.sizethumb=='auto' ? (oTrack[options.axis] * oContent.ratio) : options.sizethumb)));
			oScrollbar.ratio = options.sizethumb == 'auto' ? (oContent[options.axis]/oTrack[options.axis]) : (oContent[options.axis] - oViewport[options.axis]) / (oTrack[options.axis] - oThumb[options.axis]);
			iScroll = (sScroll == 'relative' && oContent.ratio <= 1) ? Math.min((oContent[options.axis] - oViewport[options.axis]),Math.max(0,iScroll)) : 0;
			iScroll = (sScroll == 'bottom' && oContent.ratio <= 1) ? (oContent[options.axis] - oViewport[options.axis]) : isNaN(parseInt(sScroll)) ? iScroll : parseInt(sScroll);
			setSize();
		};
		function setSize(){
			oThumb.obj.css(sDirection,iScroll/oScrollbar.ratio);
			oContent.obj.css(sDirection,-iScroll);
			iMouse['start'] = oThumb.obj.offset()[sDirection];
			var sCssSize=sSize.toLowerCase();
			oScrollbar.obj.css(sCssSize,oTrack[options.axis]);
			oTrack.obj.css(sCssSize,oTrack[options.axis]);
			oThumb.obj.css(sCssSize,oThumb[options.axis]);
		};
		function setEvents(){
			oThumb.obj.bind('mousedown',start);
			oThumb.obj[0].ontouchstart = function(oEvent){
				oEvent.preventDefault();
				oThumb.obj.unbind('mousedown');
				start(oEvent.touches[0]);
				return false;
		};
		oTrack.obj.bind('mouseup',drag);
		if (options.scroll && this.addEventListener) {
			oWrapper[0].addEventListener('DOMMouseScroll',wheel,false);
			oWrapper[0].addEventListener('mousewheel',wheel,false);
		}
		else if (options.scroll){
			oWrapper[0].onmousewheel = wheel;
		}
	};
	function start(oEvent) {
		iMouse.start = sAxis?oEvent.pageX:oEvent.pageY;
		var oThumbDir = parseInt(oThumb.obj.css(sDirection));
		iPosition.start = oThumbDir == 'auto' ? 0 : oThumbDir;
		$(document).bind('mousemove',drag);
		document.ontouchmove = function(oEvent) {
			$(document).unbind('mousemove');
			drag(oEvent.touches[0]);
		};
		$(document).bind('mouseup',end);
		oThumb.obj.bind('mouseup',end);
		oThumb.obj[0].ontouchend = document.ontouchend = function(oEvent) {
			$(document).unbind('mouseup');
			oThumb.obj.unbind('mouseup');
			end(oEvent.touches[0]);
		};
		return false;
	};
	function wheel(oEvent) {
		if (!(oContent.ratio >= 1)) {
			oEvent = $.event.fix(oEvent || window.event);
			var iDelta = oEvent.wheelDelta ? oEvent.wheelDelta/120 : -oEvent.detail/3;
			iScroll-=iDelta*options.wheel;
			iScroll = Math.min((oContent[options.axis]-oViewport[options.axis]),Math.max(0,iScroll));
			oThumb.obj.css(sDirection,iScroll/oScrollbar.ratio);
			oContent.obj.css(sDirection,-iScroll);oEvent.preventDefault();
		};
	};
	function end(oEvent) {
		$(document).unbind('mousemove',drag);
		$(document).unbind('mouseup',end);
		oThumb.obj.unbind('mouseup',end);
		document.ontouchmove = oThumb.obj[0].ontouchend = document.ontouchend = null;
		return false;
	};
	function drag(oEvent) {
		if (!(oContent.ratio >= 1)) {
			iPosition.now = Math.min((oTrack[options.axis]-oThumb[options.axis]),Math.max(0,(iPosition.start+((sAxis?oEvent.pageX:oEvent.pageY)-iMouse.start))));
			iScroll=iPosition.now*oScrollbar.ratio;oContent.obj.css(sDirection,-iScroll);oThumb.obj.css(sDirection,iPosition.now);
		;}
		return false;
	};
	return initialize();};
})(jQuery);
